题意
n
个点
题解
求强连通分量,再求入度为
0
的强连通和出度为
代码
#include <bits/stdc++.h>
#define kN 10010LL
#define kM 100010LL
#define t(p) e[0][p]
#define n(p) e[1][p]
#define s(u) st[u]
int n, e[2][kM], st[kN], te;
inline void Add(int u,int v) { ++te,t(te)=v,n(te)=s(u),s(u)=te; }
int top,idx,cntblc,dfn[kN],low[kN],sta[kN],belong[kN],ind[kN],out[kN];
bool ins[kN];
void dfs(int u) {
int v, p;
dfn[u] = low[u] = ++idx;
ins[u] = true;
sta[++top] = u;
for(p=s(u);p;p=n(p))
if (v=t(p),!dfn[v]) {
dfs(v);
if (low[v]<low[u])low[u]=low[v];
} else if(ins[v]&&dfn[v]<low[u])low[u]=dfn[v];
if (dfn[u]==low[u]) {
cntblc++;
for(v=-1;u!=v;){
v=sta[top--];
ins[v]=false;
belong[v]=cntblc;
}
}
}
inline void Tarjan() {
top = idx = cntblc = 0;
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(belong,0,sizeof belong);
for(int u=1;u<=n;u++) if(!dfn[u]) dfs(u);
}
inline void Rebuild() {
memset(ind,0,sizeof ind);
memset(out,0,sizeof out);
for(int u=1,v,p;u<=n;u++)
for(p=s(u);p;p=n(p))
if(v=t(p),belong[u]!=belong[v]) {
ind[belong[v]]++;
out[belong[u]]++;
}
}
inline void work() {
int m, i, u, v;
te = 0;
memset(st,0,sizeof st);
scanf("%d%d", &n, &m);
for(i=1;i<=m;i++) {
scanf("%d%d",&u,&v);
Add(u,v);
}
Tarjan();
Rebuild();
u=v=0;
for(i=1;i<=cntblc;i++){
if(!ind[i])u++;
if(!out[i])v++;
}
if (cntblc == 1) {
puts("0");
} else printf("%d\n",std::max(u,v));
}
int main() {
int T;
scanf("%d", &T);
while (T --> 0) work();
return 0;
}