链接:http://poj.org/problem?id=2186
题意:农场有一群奶牛。如果奶牛A认为奶牛Bpopular,奶牛B认为奶牛Cpopular,则奶牛A也认为奶牛Cpopular。
求,有没有这样被所有人都认为popular的奶牛?
有向图,先求强连通分量,再对每个分量缩点,求每个缩点的出度。
如果缩点中有且仅有一个出度为0,则该缩点内的所有奶牛均为被每一头奶牛受欢迎的。
如果不止一个缩点的出度为0,则不存在这样的奶牛。例如下面这组数据:
3 2
2 1
2 3
输出:0
#include<cstdio>
#include<cstring>
#define MAXN 10005
#define MAXE 50005
using namespace std;
int n,m;
struct Edge
{
int to;
int next;
}edge[MAXE];
int head[MAXN],dfn[MAXN],low[MAXN],stack[MAXN],instack[MAXN];
int degree[MAXN],belong[MAXN],bans[MAXN];
int ecnt,bcnt,index,top;
void add(int u,int v)
{
edge[ecnt].to=v;
edge[ecnt].next=head[u];
head[u]=ecnt++;
}
void tarjan(int u)
{
int v,i;
dfn[u]=low[u]=++index;
stack[top++]=u;
instack[u]=1;
for(i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(!dfn[v])
{
tarjan(v);
if(low[u]>low[v])
low[u]=low[v];
}
else if(instack[v]&&low[u]>dfn[v])
low[u]=dfn[v];
}
if(dfn[u]==low[u])
{
bcnt++;
do
{
v=stack[--top];
instack[v]=0;
belong[v]=bcnt;
bans[bcnt]++; //缩点
}while(u!=v);
}
}
int main()
{
int a,b;
while(scanf("%d%d",&n,&m)!=EOF)
{
ecnt=bcnt=0;
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
}
memset(dfn,0,sizeof(dfn));
memset(instack,0,sizeof(instack));
memset(belong,0,sizeof(belong));
memset(bans,0,sizeof(bans));
index=top=0;
for(int j=1;j<=n;j++)
if(!dfn[j])
tarjan(j);
for(int i=1;i<=n;i++)
{
for(int j=head[i];j!=-1;j=edge[j].next)
{
if(belong[i]!=belong[edge[j].to])//如果两个点不在一个连通分量,父节点出度加加
degree[belong[i]]++;
}
}
int pos,num=0;
for(int i=1;i<=bcnt;i++)
if(degree[i]==0)
{
pos=i;
num++;
}
if(num==1)
printf("%d\n",bans[pos]);
else
printf("%d\n",0);
}
return 0;
}