Popular Cows--POJ 2186
1、题目类型:图论、强连通分量、Tarjan算法。
2、解题思路:(1)建立图的邻接表;(2)Trajan算法求解并记录强连通分量;(3)判断强连通分量的入度,当存在多个出度为0时,输出0;当只存在唯一出度为0的强连通分量,则输出其内部节点的个数。
3、注意事项:图用邻接表表示,矩阵表示MLE;注意M=0的情况。
4、实现方法:
#include<iostream>
#include<stack>
using namespace std;
struct TNode
{
int data;
TNode *next;
};
int n,m,index,cnt,bcnt;
int dfn[10010],low[10010];
int a[50010],b[50010],flag[10010];
TNode *map[10010],data[500100];
bool vis[10010];
stack<int> S;
void Tarjan(int v)
{
TNode *tmp;
dfn[v]=low[v]=++cnt;
vis[v]=true;
S.push(v);
for(tmp=map[v];tmp!=NULL;tmp=tmp->next)
{
int i=tmp->data;
if(!dfn[i])
{
Tarjan(i);
if(low[v]>low[i])
low[v]=low[i];
}
else if(vis[i]&&low[v]>dfn[i])
{
low[v]=dfn[i];
}
}
if(low[v]==dfn[v])
{
bcnt++;
int j;
do
{
j=S.top();
S.pop();
//用于标示点j在第bcnt个强连通分量里面
flag[j]=bcnt;
}while(j!=v);
}
}
int main()
{
int i,ans,pos;
TNode *P,*pre;
cin>>n>>m;
if(m==0)
{
cout<<0<<endl;
return 0;
}
//建立邻接表
for(i=1;i<=m;i++)
{
cin>>a[i]>>b[i];
P=&data[index++];
P->data=b[i];
if(map[a[i]]==NULL)
{
map[a[i]]=P;
}
else
{
pre=map[a[i]]->next;
P->next=pre;
map[a[i]]->next=P;
}
}
for(i=1;i<=n;i++)
{
if(!dfn[i])
Tarjan(i);
}
memset(vis,0,sizeof(vis));
for(i=1;i<=m;i++)
{
if(flag[a[i]]!=flag[b[i]])
vis[flag[a[i]]]=1;
}
cnt=0;
for(i=1;i<=bcnt;i++)
{
if(!vis[i])
{
cnt++;
pos=i;
}
}
if(cnt>1)
{
cout<<0<<endl;
}
else
{
ans=0;
for(i=1;i<=n;i++)
if(flag[i]==pos)
ans++;
cout<<ans<<endl;
}
return 0;
}