受欢迎的牛
题目描述
有N头牛,M对关系(A,B),表示A认为B是受欢迎的,关系可传递,求多少头牛被出自己以外所有的牛认为是受欢迎的。
思路
由于喜欢的关系可以传递,所以这M对关系就形成了一张有向图,而要求的就是对于每一头牛它是否直接或间接被其他牛认为受欢迎,我们考虑对于一个强连通分量,在这个强连通分量中的牛一定互相认为受欢迎,我们可以直接把它看做“一头牛”。所以在进行缩点之后,必定是一张DAG,而对于这张图,我们考虑如果它符合条件,那么它的出度必定为0,否则就会形成环。并且如果出度为0的强连通分量不止一个,显然也无法达到。
代码
#include <bits/stdc++.h> using namespace std; const int N=1e4+10,M=5e5+10; int nxt[M],head[N],to[M],tot; void add_edge(int x,int y) { nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; } int dfn[N],low[N],st[N],idx,co[N],col,top,siz[N]; void tarjan(int u) { dfn[u]=low[u]=++idx; st[++top]=u; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(!co[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { co[u]=++col; ++siz[col]; while(st[top]!=u) { ++siz[col]; co[st[top]]=col; --top; } --top; } } int out[N]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { int x,y; scanf("%d%d",&x,&y); add_edge(x,y); } for(int i=1;i<=n;++i) if(!dfn[i])tarjan(i); int ans=0,sum=0; for(int i=1;i<=n;++i) for(int j=head[i];j;j=nxt[j]) if(co[i]!=co[to[j]])++out[co[i]]; for(int i=1;i<=col;++i) if(!out[i])ans=siz[i],++sum; if(sum==1)printf("%d",ans); else printf("0"); return 0; }