1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| #include <iostream> #include <cstdio> #include <stack> #include <cstring> #define init(x) memset (x,0,sizeof (x)) using namespace std; const int MAXN = 1e5 + 5; int t,n,m,cnt,times,scc_cnt,num1,num2; int dfn[MAXN],low[MAXN],vis[MAXN],in[MAXN],out[MAXN]; int head[MAXN << 1],to[MAXN << 1],nxt[MAXN << 1]; stack <int> s; void _add (int u,int v); void tarjan (int u); int main () { scanf ("%d",&t); while (t--) { cnt = times = scc_cnt = num1 = num2 = 0; init (dfn);init (low);init (vis);init (in);init (out); init (head);init (to);init (nxt); scanf ("%d%d",&n,&m); for (int i = 1;i <= m;++i) { int x,y;scanf ("%d%d",&x,&y); _add (x,y); } for (int i = 1;i <= n;++i) if (!dfn[i]) tarjan (i); for (int i = 1;i <= n;++i) { for (int j = head[i];j;j = nxt[j]) { int v = to[j]; if (vis[i] != vis[v]) ++out[vis[i]],++in[vis[v]]; } } if (scc_cnt == 1) { printf ("0\n"); continue; } for (int i = 1;i <= scc_cnt;++i) { if (!in[i]) ++num1; if (!out[i]) ++num2; } printf ("%d\n",max (num1,num2)); } return 0; } void _add (int u,int v) { to[++cnt] = v; nxt[cnt] = head[u]; head[u] = cnt; } void tarjan (int u) { low[u] = dfn[u] = ++times; s.push (u); for (int i = head[u];i;i = nxt[i]) { int v = to[i]; if (!dfn[v]) { tarjan (v); low[u] = min (low[u],low[v]); } else if (!vis[v]) low[u] = min (low[u],dfn[v]); } if (low[u] == dfn[u]) { ++scc_cnt; while (1) { int x = s.top ();s.pop (); vis[x] = scc_cnt; if (x == u) break; } } }
|