题目:https://vjudge.net/problem/POJ-2186
求从其他所有点可以到达的点的个数
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e4+10;
const int M=5e4+10;
int h[N],e[M],ne[M],idx;
int dfn[N],low[N],st[N],in[N],num[N],size[N],out[N],c,top,cnt;
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
void dfs(int x)
{
dfn[x]=low[x]=++c;
st[++top]=x;in[x]=1;
for(int i=h[x];i!=-1;i=ne[i])
{
int j=e[i];
if(!dfn[j])
{
dfs(j);
low[x]=min(low[x],low[j]);
}
else if(in[j])
{
low[x]=min(low[x],dfn[j]);
}
}
if(low[x]==dfn[x])
{
int y;
cnt++;
do{
y=st[top--];
in[y]=0;
size[cnt]++;
num[y]=cnt;
}while(x!=y);
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
}
for(int i=1;i<=n;i++)
{
if(dfn[i]==0)
{
dfs(i);
}
}
//tarjan之后联通分量编号从大到小是拓扑序
for(int i=1;i<=n;i++)
{
for(int j=h[i];j!=-1;j=ne[j])
{
if(num[i]!=num[e[j]])
{
out[num[i]]++;
}
}
}
int ans=0;
int flag=0;
for(int i=1;i<=cnt;i++)
{
if(out[i]==0)
{
flag++;
ans=size[i];
if(flag>1)
{
ans=0;
break;
}
}
}
cout<<ans<<endl;
}