#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
ifstream in("sortaret.in");
ofstream out("sortaret.out");
class Graf
{
int tip;
int nr_noduri;
int nr_muchii;
vector <vector <int>> lista_vecini;
public:
Graf() {
tip = 0;
nr_noduri = 0;
nr_muchii = 0;
}
Graf(int tip, int nr_noduri, int nr_muchii, vector <vector<int>> lista_vecini) {
this->tip = tip;
this->nr_noduri = nr_noduri;
this->nr_muchii = nr_muchii;
this->lista_vecini.resize(nr_noduri + 1);
for (int i = 1; i <= nr_noduri; i++)
for (int j = 0; j < lista_vecini[i].size(); j++)
this->lista_vecini[i].push_back(lista_vecini[i][j]);
}
~Graf() { }
friend istream& operator>>(istream& in, Graf& g);
friend ostream& operator<<(ostream& out, const Graf& g);
void BFS() {
cout << "\nIntroduceti nodul de start: ";
int start;
cin >> start;
queue <int> bfs_tree;
vector <int> viz;
for (int i = 0; i <= this->nr_noduri; i++)
viz.push_back(-1);
bfs_tree.push(start);
viz[start] = 0;
while (!bfs_tree.empty()) {
int nod_curent = bfs_tree.front();
bfs_tree.pop();
for (int i = 0; i < lista_vecini[nod_curent].size(); i++)
if (viz[lista_vecini[nod_curent][i]] == -1) {
viz[lista_vecini[nod_curent][i]] = viz[nod_curent] + 1;
bfs_tree.push(lista_vecini[nod_curent][i]);
}
}
cout << "\nVectorul distantelor: ";
for (int i = 1; i <= this->nr_noduri; i++)
cout << viz[i] << " ";
}
void DFS(int start, vector <int> &viz) {
stack <int> dfs_tree;
dfs_tree.push(start);
viz[start] = 1;
while (!dfs_tree.empty()) {
int nod_curent = dfs_tree.top();
int vecin = 0;
for (int i = 0; i < lista_vecini[nod_curent].size(); i++)
if (viz[lista_vecini[nod_curent][i]] == 0) {
vecin = lista_vecini[nod_curent][i];
break;
}
if (vecin == 0)
dfs_tree.pop();
else {
dfs_tree.push(vecin);
viz[vecin] = 1;
}
}
}
void comp_conexe() {
vector <int> viz;
for (int i = 0; i <= this->nr_noduri; i++)
viz.push_back(0);
int nr_comp = 0;
for(int i=1; i<=this->nr_noduri; i++)
if(viz[i] == 0) {
DFS(i, viz);
nr_comp++;
}
cout << "\nNumar de componente conexe: " << nr_comp << " ";
}
void havel_hakimi() {
int seq_len;
vector <int> seq;
int sum = 0;
int ok = 1;
cin >> seq_len;
for (int i = 0; i < seq_len; i++) {
int aux;
cin >> aux;
seq.push_back(aux);
sum = sum + aux;
if (aux > seq_len - 1)
ok = 0;
}
if (sum % 2 != 0 || ok == 0)
cout << "Nu";
else {
sort(seq.begin(), seq.end(), greater<int>());
while (seq[0] != 0) {
int nod_curent = seq[0];
seq.erase(seq.begin());
for (int i = 0; i < nod_curent; i++) {
seq[i]--;
if (seq[i] < 0) {
cout << "Nu";
ok = 0;
break;
}
}
sort(seq.begin(), seq.end(), greater<int>());
}
if (ok == 1)
cout << "Da";
}
}
void dfs_muchiiIntoarcere(int i, vector <int>& viz, vector <int>& niv, vector<int>& niv_min, vector <vector<int>>& solutie) {
viz[i] = 1;
niv_min[i] = niv[i];
for (int j = 0; j < lista_vecini[i].size(); j++)
if (viz[lista_vecini[i][j]] == 0) {
niv[lista_vecini[i][j]] = niv[i] + 1;
dfs_muchiiIntoarcere(lista_vecini[i][j], viz, niv, niv_min, solutie);
niv_min[i] = min(niv_min[i], niv_min[lista_vecini[i][j]]);
if (niv_min[lista_vecini[i][j]] > niv[i]) {
solutie.push_back({ i,lista_vecini[i][j] });
}
}
else {
if (niv[lista_vecini[i][j]] < niv[i] - 1)
niv_min[i] = min(niv_min[i], niv[lista_vecini[i][j]]);
}
}
void criticalConnections() {
vector <vector<int>> solutie;
vector <int> viz;
vector <int> niv;
vector <int> niv_min;
for (int i = 0; i <= nr_noduri; i++)
viz.push_back(0);
niv.resize(nr_noduri + 1);
niv_min.resize(nr_noduri + 1);
niv[1] = 1;
dfs_muchiiIntoarcere(1, viz, niv, niv_min, solutie);
for (int i = 0; i < solutie.size(); i++)
cout << solutie[i][0] << " " << solutie[i][1] << "\n";
}
void tare_conex(int i, vector <int> &onStack, vector <int> &viz, vector <int> &niv_min, int &index, stack <int> &s, int &nr, vector <vector<int>> &solutie) {
viz[i] = index;
niv_min[i] = index;
index++;
s.push(i);
onStack[i] = 1;
for (int j = 0; j < lista_vecini[i].size(); j++)
if (viz[lista_vecini[i][j]] == 0) {
tare_conex(lista_vecini[i][j], onStack, viz, niv_min, index, s, nr, solutie);
niv_min[i] = min(niv_min[i], niv_min[lista_vecini[i][j]]);
}
else if (onStack[lista_vecini[i][j]] == 1)
niv_min[i] = min(niv_min[i], viz[lista_vecini[i][j]]);
int j = 0;
if (niv_min[i] == viz[i]) {
nr++;
while (s.top() != i) {
j = s.top();
solutie[nr].push_back(j);
onStack[j] = 0;
s.pop();
}
j = s.top();
solutie[nr].push_back(j);
onStack[j] = 0;
s.pop();
}
}
void tarjan() {
vector <int> onStack;
vector <int> viz;
vector <int> niv_min;
vector <vector<int>> solutie;
int nr = 0;
niv_min.resize(nr_noduri + 1);
solutie.resize(nr_noduri + 1);
for (int i = 0; i <= nr_noduri; i++) {
onStack.push_back(0);
viz.push_back(0);
}
int index = 1;
stack <int> s;
for (int i = 1; i <= nr_noduri; i++)
if (viz[i] == 0)
tare_conex(i, onStack, viz, niv_min, index, s, nr, solutie);
cout << nr << "\n";
for (int i = 1; i <= nr; i++) {
for (int j = 0; j < solutie[i].size(); j++)
cout << solutie[i][j] << " ";
cout << "\n";
}
}
void dfs_sortare(int nod_curent, vector <int> &viz, vector <int> &solutie) {
viz[nod_curent] = 1;
solutie.push_back(nod_curent);
for (int i = 0; i < lista_vecini[nod_curent].size(); i++)
if (viz[lista_vecini[nod_curent][i]] == 0)
dfs_sortare(lista_vecini[nod_curent][i], viz, solutie);
}
void sortare_top() {
vector <int> solutie;
vector <int> viz;
for (int i = 0; i <= nr_noduri; i++)
viz.push_back(0);
for (int i = 1; i <= nr_noduri; i++)
if (viz[i] == 0)
dfs_sortare(i, viz, solutie);
for (int i = 0; i < solutie.size(); i--)
out << solutie[i] << " ";
//out << "\n";
}
};
istream& operator>>(istream& in, Graf& g)
{
cout << "\nIntroduceti tipul grafului (0-Neorientat 1-Orientat):";
in >> g.tip;
if (g.tip == 0) {
cout << "\nIntroduceti numarul de noduri: ";
cin >> g.nr_noduri;
cout << "\nIntroduceti numarul de muchii: ";
cin >> g.nr_muchii;
cout << "\nIntroduceti lista muchiilor: ";
g.lista_vecini.resize(g.nr_noduri + 1);
for (int i = 0; i < g.nr_muchii; i++) {
int x, y;
cin >> x >> y;
g.lista_vecini[x].push_back(y);
g.lista_vecini[y].push_back(x);
}
}
else if(g.tip == 1) {
cout << "\nIntroduceti numarul de noduri: ";
cin >> g.nr_noduri;
cout << "\nIntroduceti numarul de arce: ";
cin >> g.nr_muchii;
cout << "\nIntroduceti lista arcelor: ";
g.lista_vecini.resize(g.nr_noduri + 1);
for (int i = 0; i < g.nr_muchii; i++) {
int x, y;
cin >> x >> y;
g.lista_vecini[x].push_back(y);
}
}
else {
cout << "\nTip gresit";
}
return in;
}
ostream& operator<<(ostream& out, const Graf& g)
{
cout << "\nTip graf: ";
if (g.tip == 0) {
cout << "neorientat";
cout << "\nNumar de noduri: " << g.nr_noduri;
cout << "\nNumar de muchii: " << g.nr_muchii;
cout << "\nLista de vecini: ";
for (int i = 1; i <= g.nr_noduri; i++)
{
for (int j = 0; j < g.lista_vecini[i].size(); j++)
cout << g.lista_vecini[i][j] << " ";
cout << "\n";
}
}
else if (g.tip == 1) {
cout << "orientat";
cout << "\nNumar de noduri: " << g.nr_noduri;
cout << "\nNumar de arce: " << g.nr_muchii;
cout << "\nLista de vecini: ";
for (int i = 1; i <= g.nr_noduri; i++)
{
for (int j = 0; j < g.lista_vecini[i].size(); j++)
cout << g.lista_vecini[i][j] << " ";
cout << "\n";
}
}
return out;
}
int main()
{
int n, m;
in >> n >> m;
vector <vector <int>> v;
v.resize(n + 1);
for (int i = 0; i < m; i++)
{
int x, y;
in >> x >> y;
v[x].push_back(y);
//v[y].push_back(x);
}
Graf G(1, n, m, v);
G.sortare_top();
return 0;
}