有向图的强连通+缩点。
题目要求要有多少头牛被所有牛喜欢,那么也就是求缩点以后出度为零的点对应的牛的个数或者所有点的出度都不为零,那么也就是说这个图是强连通图,所有点都可以互相到达,即所有牛都被其他牛喜欢,这时输出n就可以了,并且只有当出度为零的点不存在或只有一个才存在一些牛被其他所有牛喜欢。
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int maxe=50005;
struct Edge{
int next;
int v;
}edge[maxe];
int head[maxe],stack[maxe],vis[maxe],index[maxe],out[maxe],num[maxe],low[maxe],dfn[maxe];
int n,m,e,pnt,cnt,top;
void build_adge(int a,int b)
{
edge[e].v=b; edge[e].next=head[a]; head[a]=e++;
}
void target(int v)
{
dfn[v]=low[v]=++cnt;
int u,w;
stack[++top]=v; vis[v]=1;
for(int i=head[v];i!=-1;i=edge[i].next)
{
w=edge[i].v;
if(!dfn[w])
{
target(w);
low[v]=min(low[w],low[v]);
}
else if(vis[w]) low[v]=min(low[v],dfn[w]);
}
if(low[v]==dfn[v])
{
pnt++;
do{u=stack[top--]; vis[u]=0; index[u]=pnt; num[pnt]++; }while(u!=v);
}
}
int get()
{
int ans,x=0;
pnt=cnt=top=0;
memset(dfn,0,sizeof(dfn));
memset(num,0,sizeof(num));
for(int i=1;i<=n;i++)
{
if(!dfn[i]) target(i);
}
if(pnt==1) return n;
memset(out,0,sizeof(out));
for(int i=1;i<=n;i++)
for(int j=head[i];j!=-1;j=edge[j].next)
{
if(index[i]!=index[edge[j].v]) {out[index[i]]++;}
}
for(int i=1;i<=pnt;i++)
{
if(out[i]==0) { ans=i; x++;}
}
if(x>1) return 0;
if(x==0) return n;
return num[ans];
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
e=0;
int a,b;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
build_adge(a,b);
}
printf("%d\n",get());
}
return 0;
}
poj 2186 Popular Cows
最新推荐文章于 2019-05-06 16:34:00 发布