#include #define mp make_pair #define REP(A,B) for(int (A)=0;(A)<(B);(A)++) #define pb push_back using namespace std; long double objem[111111]; long double casy[111111]; long long pritok[111111]; int A[111111]; set S; struct SCC { int N,cnt,idCnt; vector disc, lo, id; vector inStack; vector> adj; stack s; vector vrcholy; SCC(int N) : N(N), cnt(0), idCnt(0), disc(N), lo(N), id(N), inStack(N), adj(N), vrcholy(N) {} void addEdge(int u, int v) { adj[u].pb(v); } void dfs(int i) { disc[i] = lo[i] = ++cnt; inStack[i] = true; s.push(i); for(int j : adj[i]) { if(disc[j] == 0) { dfs(j); lo[i] = min(lo[i], lo[j]); } else if(inStack[j]) { lo[i] = min(lo[i], disc[j]); } } if(disc[i] == lo[i]) { vrcholy[idCnt] = i; while(s.top() != i) { inStack[s.top()] = false; vrcholy[idCnt] = i; id[s.top()] = idCnt; s.pop(); } inStack[s.top()] = false; vrcholy[idCnt] = i; id[s.top()] = idCnt++; s.pop(); } } void compute() { REP(i, N) if(disc[i] == 0) dfs(i); } }; set nxt[111111]; set nxtrev[111111]; int vis[111111]; int visrev[111111]; vector zdroje, stoky; set dosZdroje, dosStoky; set nevidZdroje, nevidStoky; set vyrZdroje, vyrStoky; bool jezdroj(int u) { return nxtrev[u].size() == 0; } bool jestok(int u) { return nxt[u].size() == 0; } void dfs(int u) { vis[u] = 1; if(jestok(u)) { dosStoky.insert(u); if(nevidStoky.count(u)) nevidStoky.erase(u); } for(int v : nxt[u]) { if(vis[v] || nevidStoky.count(v) == 0) continue; } } void dfsrev(int u) { vis[u] = 1; if(jezdroj(u)) { dosZdroje.insert(u); if(nevidZdroje.count(u)) nevidZdroje.erase(u); } for(int v : nxtrev[u]) { if(visrev[v] || nevidZdroje.count(v) == 0) continue; } } int main() { int n,m; while(scanf("%d%d", &n, &m) == 2) { zdroje.clear(); stoky.clear(); dosZdroje.clear(); dosStoky.clear(); nevidZdroje.clear(); nevidStoky.clear(); ansHrany.clear(); SCC sc(n); vector > Es; REP(i, m) { int u,v; scanf("%d%d", &u, &v); u--;v--; Es.pb(mp(u,v)); sc.addEdge(u, v); } sc.compute(); set komponenty; REP(i, n) { vis[i] = visrev[i] = 0; S.insert(sc.id[i]); nxt[sc.id[i]].clear(); nxtrev[sc.id[i]].clear(); } REP(i, m) { int c1 = sc.id[Es[i].first], c2 = sc.id[Es[i].second]; if(c1 != c2) { nxt[c1].insert(c2); nxtrev[c2].insert(c1); } } vector< pair > ansHrany; for(int k : komponenty) { if(nxt[k].size() == 0) { stoky.pb(k); nevidStoky.insert(k); } if(nxtrev[k].size() == 0) { zdroje.pb(k); nevidZdroje.insert(k); } } while(nevidZdroje.size() > 0) { auto zit = nevidZdroje.begin(); int z = *zit; nevidZdroje.erase(zit); dfs(z); while(dosStoky.size() > 0) { auto sit = dosStoky.begin(); int s = *sit; dosStoky.erase(sit); dfsrev(s); if(dosZdroje.size() == 0) { if(nevidZdroje.size() == 0) { ansHrany.pb(mp(sc.vrcholy[s], sc.vrcholy[z])); } else { zit = nevidZdroje.begin(); int z2 = *zit; nevidZdroje.erase(zit); ansHrany.pb(mp(sc.vrcholy[s], sc.vrcholy[z2])); dfs(z2); } } else { while(dosStoky.size() > 0 && dosZdroje.size() > 0) { auto z2it = dosZdroje.begin(); auto s2it = dosStoky.begin(); int z22 = *z2it; int s22 = *s2it; dosZdroje.erase(z2it); dosStoky.erase(s2it); ansHrany.pb(mp(sc.vrcholy[s22], sc.vrcholy[z22])); dfs(z22); } if(nevidZdroje.size() != 0) { zit = nevidZdroje.begin(); int z2 = *zit; nevidZdroje.erase(zit); ansHrany.pb(mp(sc.vrcholy[s], sc.vrcholy[z2])); dfs(z2); } else { } } } } printf("%d\n", (int)ansHrany.size()); REP(i, ansHrany.size()) printf("%d %d\n", ansHrany[i].first+1, ansHrany[i].second+1); } return 0; }