题目链接:POJ 2186
解题思路:
先用tarjan算法求出图中的强连通分量,再求出缩点后唯一的叶结点即可。
代码:
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,m,dfn[100005],low[100005],cnt;
int scnt,stack[100005],scc,vis[100005],ans[100005];
bool instack[100005];
vector<int> vec[100005];
void tarjan(int index)
{
int tmp;
dfn[index]=low[index]=++cnt;
instack[index]=1, stack[++scnt]=index;
for(int i=0;i<vec[index].size();i++)
{
tmp=vec[index][i];
if(!dfn[tmp])
{
tarjan(tmp);
low[index]=min(low[index],low[tmp]);
}
else if(instack[tmp])
{
low[index]=min(low[index],dfn[tmp]);
}
}
if(dfn[index]==low[index])
{
scc++;
do{
tmp=stack[scnt--];
instack[tmp]=false;
vis[tmp]=scc,ans[scc]++;
}
while(tmp!=index);
}
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
memset(vec,0,sizeof(vec));
int x,y;
while(m--)
{
scanf("%d %d",&x,&y);
vec[x].push_back(y);
}
cnt=scc=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(instack,0,sizeof(instack));
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
cnt=0;
memset(dfn,0,sizeof(dfn));
for(int i=1;i<=n;i++)
{
for(int j=0;j<vec[i].size();j++)
{
if(vis[i]!=vis[vec[i][j]])
dfn[vis[i]]=1;
}
}
for(int i=1;i<=scc;i++)
if(!dfn[i])
{
cnt++;
}
if(cnt==1)
{
printf("%d\n",ans[1]);
}
else
{
printf("0\n");
}
}
return 0;
}