缩点
对于一个强连通分量,里面的所有点都是等效的,任意一个点被欢迎等价于全部被欢迎,任意一个去欢迎等价于全部去欢迎,于是把他们缩起来。
缩完得到一棵树,只需判断出度为零点是否唯一即可
#include<cstdio>
#include<algorithm>
#define N 10005
#define M 50005
using namespace std;
struct edge{int next,to;}e[M];
int ecnt=0, last[N], cnt=0, dfn[N], low[N], sta[N], top=0, times=0, belong[N], siz[N];
bool out[N];
void add(int a, int b)
{
e[++ecnt]=(edge){last[a],b};
last[a]=ecnt;
}
void tarjan(int x)
{
sta[++top]=x;
dfn[x]=low[x]=++times;
for(int i = last[x]; i; i=e[i].next)
{
int y=e[i].to;
if(dfn[y])low[x]=min(low[x],dfn[y]);
else{tarjan(y);low[x]=min(low[x],low[y]);}
}
if(dfn[x]==low[x])
{
++cnt;
siz[cnt]=1;
while(sta[top]!=x)
{
belong[sta[top--]]=cnt;
siz[cnt]++;
}
belong[sta[top--]]=cnt;
}
}
int main()
{
int n, m;
scanf("%d%d",&n,&m);
for(int i = 1, a, b; i <= m; i++)
{
scanf("%d%d",&a,&b);
add(a,b);
}
for(int i = 1; i <= n; i++)
if(!dfn[i])
tarjan(i);
for(int x = 1; x <= n; x++)
for(int i = last[x]; i; i=e[i].next)
{
int y=e[i].to;
if(belong[x]!=belong[y])
out[belong[x]]=1;
}
int ans=0;
for(int i = 1; i <= cnt; i++)
if(!out[i])
{
if(ans)return !printf("0\n");
ans=siz[i];
}
printf("%d\n",ans);
return 0;
}