题目链接:http://poj.org/problem?id=2186
思路:一个有向无环图中如果有只有一个出度为零的点,则其他点均可通过路径到达该点,则这个点就是最受崇拜的大牛。所以我们用强连通缩点,将每一个强连通分量看成一点,这样就可以把一个有换图转换成无环图。
第一道强连通,哈哈哈存一下。
#include<cstdio>
#include<cstring>
using namespace std;
const int N=10005;
int n,m,e,head[N],dfn[N],low[N];
int stack[N],top,insta[N];//stack模拟栈,insta判断是否在栈中
int cnt,index,belong[N],out[N];//每个强连通分量中的点对应相同的index,belong[i]记录i的index值,out记录缩点后的各个点的出度,就是不同index对应的出度
int min(int a,int b)
{
if(a<b)
return a;
return b;
}
struct node
{
int u,next;
}edge[50005];
void add(int a,int b)
{
edge[e].u=b;
edge[e].next=head[a];
head[a]=e++;
}
void Tarjan(int a)
{
int i,v;
dfn[a]=low[a]=cnt++;
insta[a]=1;
stack[++top]=a;//stack从1开始存数据
for(i=head[a];i!=-1;i=edge[i].next)
{
v=edge[i].u;
if(dfn[v]==-1)
{
Tarjan(v);
low[a]=min(low[a],low[v]);
}
else if(insta[v])
{
low[a]=min(low[a],dfn[v]);
}
}
if(low[a]==dfn[a])
{
index++;
do
{
v=stack[top--];
insta[v]=0;
belong[v]=index;
}
while(top!=0&&v!=a);
}
}
int main()
{
int i,a,b,v,num,ans,temp;
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(head,-1,sizeof(head));
e=0;top=0;index=0;cnt=1;
memset(dfn,-1,sizeof(dfn));
memset(low,-1,sizeof(low));
memset(belong,0,sizeof(belong));
memset(out,0,sizeof(out));
memset(insta,0,sizeof(insta));
for(i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
}
for(i=1;i<=n;i++)
if(dfn[i]==-1)
Tarjan(i);
for(i=1;i<=n;i++)
{
for(v=head[i];v!=-1;v=edge[v].next)
if(belong[i]!=belong[edge[v].u])
out[belong[i]]++;
}
num=0;
for(i=1;i<=index;i++)
{
if(!out[i])
{
num++;
temp=i;
}
}
ans=0;
if(num==1)
{
for(i=1;i<=n;i++)
if(belong[i]==temp)
ans++;
printf("%d\n",ans);
}
else
printf("0\n");
}
return 0;
}