对tarjan算法仍然有不够理解的地方。
#include<iostream>
#include<cstdio>
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,r,l) for(int i=(r);i>=(l);i--)
#define random(l,r) ((l)+rand()%((r)-(l)+1))
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
const int inf=1e9+10,N=1e4+10,M=5e4+10;
const double eps=1e-6;
int n,m,u,v,chudu[N],cnt[N],ans=-1;//缩点后强连通子图的出度与强联通子图中点的个数
int nxt[M],h[N],to[M],l;//链式向前星
int col[N],bianhao,dfn[N],low[N],tme;//染色数组、dfs序、能回到的最早祖先的时间戳、计时器。
int mystack[N],top;
bool vis[N],instack[N];
void addedge(int a,int b){ nxt[++l]=h[a]; h[a]=l; to[l]=b; }
void tarjan(int v){
dfn[v]=low[v]=++tme;//时间戳很重要,不能忘记。
vis[v]=instack[v]=true;
mystack[++top]=v;
for(int i=h[v];i!=0;i=nxt[i]){
int u=to[i];
if(!vis[u]){
tarjan(u);
low[v]=min(low[v],low[u]);
}else if(instack[u]) low[v]=min(low[v],dfn[u]);//为什么要在栈中才处理呢?
}
if(dfn[v]==low[v]){
col[v]=++bianhao;
instack[v]=false;
cnt[bianhao]++;
while(mystack[top]!=v){
col[mystack[top]]=bianhao;
instack[mystack[top]]=false;
cnt[bianhao]++;
top--;
}
top--;
}
}
int main(){
ios::sync_with_stdio(false); cin.tie(0);
cin>>n>>m;
rep(i,1,m){
cin>>u>>v;
addedge(u,v);
}
rep(i,1,n) if(!vis[i]) tarjan(i);记得要每个点都tarjan
rep(i,1,n) for(int j=h[i];j!=0;j=nxt[j])
if(col[i]!=col[to[j]]) chudu[col[i]]++;
rep(i,1,bianhao)
if(chudu[i]==0)
if(ans==-1) ans=cnt[i];
else { ans=0; break; }
cout<<max(ans,0);
return 0;
}