解析:
因为强连通分量内部每个点都可以互打,然后缩点。根据拓扑序判断每个强连通分量是否为出度为0的点,如果是代表着任何一点都可以到达这个强连通分量
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int e[N<<1],ne[N<<1],h[N<<1],idx;
int low[N],dfn[N];
int id[N],sz[N],cnt,scc;
int n,m;
bool st[N];
int in[N];
stack<int> q;
void add(int a,int b)
{
e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
void tarjan(int u)
{
dfn[u]=low[u]=++cnt;
q.push(u);st[u]=true;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(!dfn[j]){
tarjan(j);
low[u]=min(low[u],low[j]);
}
else if(st[j]){
low[u]=min(low[u],dfn[j]);
}
}
if(low[u]==dfn[u])
{
++scc;
int y;
do{
y=q.top();q.pop();
id[y]=scc;
sz[scc]++;
st[y]=false;
}while(y!=u);
}
}
int main()
{
scanf("%d %d",&n,&m);
memset(h,-1,sizeof h);
for(int i=1,u,v;i<=m;i++)
{
scanf("%d %d",&u,&v);
add(u,v);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++)
for(int j=h[i];~j;j=ne[j]){
int v=e[j];
int a=id[i];
int b=id[v];
if(a!=b) in[a]++;
}
int sum=0,ret=0;
for(int i=1;i<=scc;i++){
if(!in[i]){
ret++;
sum+=sz[i];
if(ret>1){
sum=0;
break;
}
}
}
printf("%d\n",sum);
}