POJ 2186 Popular Cows【强连通分量】
题意:有 N 个奶牛,奶牛A可能认为B 优秀,奶牛B可能认为C优秀,这种关系具有单向传递性,即在此情况下,奶牛A认为奶牛C也是优秀的,但奶牛B不一定认为A优秀,
问可以找出有多少个奶牛可以被其他所有奶牛都认为是优秀的。
分析:如果奶牛A认为奶牛B优秀,就连一条从B到A的边,求出强连通分量并染色缩点,最后计算入度为0 的强连通分量是否只有一个,如果是则输出该强连通分量内点的
个数,否则就不存在满足条件的奶牛。
#include<stdio.h> #include<string.h> #define clr(x)memset(x,0,sizeof(x)) #define min(a,b)(a)<(b)?(a):(b) #define maxn 100005 struct node { int to,next; }e[50005]; int tot; int head[10005]; void add(int s,int u) { e[tot].to=u; e[tot].next=head[s]; head[s]=tot++; } int sn,ti,top; bool ins[maxn]; int dfn[maxn]; int low[maxn]; int stack[maxn]; int col[maxn]; int in[maxn]; void tarjan(int u) { dfn[u]=low[u]=++ti; stack[++top]=u; ins[u]=true; int i,k; for(i=head[u];i;i=e[i].next) { k=e[i].to; if(dfn[k]==0) { tarjan(k); if(low[k]<low[u]) low[u]=low[k]; } else if(ins[k]&&dfn[k]<low[u]) low[u]=dfn[k]; } if(dfn[u]==low[u]) { sn++; do { k=stack[top--]; ins[k]=false; col[k]=sn; }while(k!=u); } } int main() { int a,b,n,m,i,j,k,res; while(scanf("%d%d",&n,&m)!=EOF) { tot=1; sn=top=ti=0; clr(col); clr(low); clr(dfn); clr(ins); clr(head); clr(in); while(m--) { scanf("%d%d",&a,&b); add(b,a); } for(i=1;i<=n;i++) if(dfn[i]==0) tarjan(i); res=0; for(i=1;i<=n;i++) for(j=head[i];j;j=e[j].next) { k=e[j].to; if(col[k]!=col[i]) { in[col[k]]++; } } res=0; for(i=1;i<=sn;i++) if(in[i]==0) res++; if(res!=1) { printf("0\n"); continue; } res=0; for(i=1;i<=n;i++) if(in[col[i]]==0) res++; printf("%d\n",res); } return 0; }