structEdge { int to, next; } e[maxm]; int c1, head[maxn]; inlinevoidadd_edge(int u, int v){ e[c1].to = v; e[c1].next = head[u]; head[u] = c1++; }
int dfn[maxn], low[maxn], c2, bl[maxn], scc; bool ins[maxn]; stack<int> S; voidtarjan(int u){ dfn[u] = low[u] = ++c2; ins[u] = 1; S.push(u); for (int i = head[u]; ~i; i = e[i].next) { int v = e[i].to; if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]); elseif (ins[v]) low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { int t; ++scc; do { t = S.top(); S.pop(); ins[t] = 0; bl[t] = scc; } while (t != u); } }
int in[maxn], out[maxn]; voidrebuild(){ for (int u = 1; u <= n; ++u) for (int i = head[u]; ~i; i = e[i].next) { int v = e[i].to; if (bl[u] == bl[v]) continue; ++in[bl[v]]; ++out[bl[u]]; } }
voidwork(){ cin >> n >> m; init(); for (int i = 1; i <= m; ++i) { int x, y; scanf("%d%d", &x, &y); add_edge(x, y); } for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i); rebuild(); int s1 = 0, s2 = 0; if (scc == 1) return (void) puts("0"); for (int i = 1; i <= scc; ++i) { s1 += !in[i]; s2 += !out[i]; } cout << max(s1, s2) << endl; }
intmain(){ int T; cin >> T; while (T--) work(); return0; }