http://poj.org/problem?id=2186
题意 :给你n头牛,m对关系,每对关系由两个编号组成,u和v代表着u认为v是受欢迎的,如果1认为2是受欢迎的,2认为3是受欢迎的,那1认为3也是受欢迎的。
思路 :强联通分量的Tarjan做法,将这些牛之间的关系看成一个有向图,最受欢迎的那个牛的那个点一定是出度为0的点。Tarjan的基本资料:http://hi.baidu.com/lydrainbowcat/item/1c664b662b1a1692c4d2491c
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <stack> #include <string.h> #include <stdlib.h> #include <algorithm> #include <iostream> using namespace std; const int maxn = 10002 ; const int maxm = 50002 ; stack<int >Q ; int head[maxn],ID[maxn],low[maxn],dfn[maxn],in[maxn],out[maxn] ; int cnt,cntt,n,m ,ans; struct node { int v,next,id ; }Edge[maxm] ; void addedge(int u,int v,int w) { Edge[w].v = v ; Edge[w].next = head[u] ; head[u] = w ; } void tarjan(int u) { int v,t ; int minn = dfn[u] = low[u] = cnt++ ; Q.push(u) ; for(int k = head[u] ; k+1 ; k = Edge[k].next) { v = Edge[k].v ; if(dfn[v] == -1) tarjan(v) ; minn = min(minn,low[v]) ; } if(minn < low[u]) {low[u] = minn ; return ;} do { ID[t = Q.top()] = cntt ; low[t] = n ; out[cntt]++ ; Q.pop() ; }while(t != u) ; cntt++ ; } void Init() { memset(head,-1,sizeof(head)) ; memset(dfn,-1,sizeof(dfn)) ; memset(in,0,sizeof(in)) ; memset(out,0,sizeof(out)) ; cnt = cntt = ans = 0 ; } int main() { while(~scanf("%d %d",&n,&m)) { Init() ; int u,v ,flag; for(int i = 0 ; i < m ; i++) { scanf("%d %d",&u,&v) ; addedge(u-1,v-1,i) ; } for(int i = 0 ; i < n ; i++) if(dfn[i] == -1) tarjan(i) ; for(int i = 0 ; i < n ; i++) { for(int j = head[i] ; j+1 ; j = Edge[j].next) { int a = ID[i],b = ID[Edge[j].v] ; if(a != b) in[ID[i]]++ ; } } for(int i = 0 ; i < cntt ; i++) { if(!in[i]) { ans++ ; flag = i ; } } if(ans == 1) printf("%d\n",out[flag]) ; else printf("0\n") ; } return 0; }