Link: http://poj.org/problem?id=2186
注意题中 是 considered popular by every other cow 意思是除了他自己其他牛都喜欢他的
我一开始理解为 the most popular =-=
利用tarjan算出强连通分支 缩点 得出出度为0的个数num(num一定不会等于0的)
如果num为1 则为该强连通图的牛个数
否则 没有这样的牛
NOTE: 题中说明是稀疏图 最好用邻接表


#include <cstdio> #include <iostream> #include <stack> using std::stack; const int maxn = 10005, INF = (1<<30); bool vis[maxn], inStack[maxn]; int dfn[maxn], low[maxn], belong[maxn], size[maxn], m, n, round, cnt; int out[maxn]; struct node { int index; node *next; }edge[maxn]; stack<int> s; int min(int a, int b) { return a<=b ?a :b ; } void tarjan(int u) { int i; dfn[u] = low[u] = round ++ ; vis[u] = 1; inStack[u] = 1; s.push(u); node *p = edge[u].next; while( p != NULL ) { int v = p->index; if( !vis[v] ) { tarjan(v); low[u] = min(low[u], low[v]); } else if( inStack[v] ) low[u] = min(low[u], dfn[v]); p = p->next; } if( low[u] == dfn[u] ) { cnt ++; while(i = s.top()) { size[cnt] ++; belong[i] = cnt; inStack[i] = 0; s.pop(); if( i==u ) break; } } } void init() { cnt = 0, round = 1; } int check() { for(int i=1; i<=n; i++) if( !vis[i] ) return i; return 0; } int main() { int i, a, b; scanf("%d %d", &n, &m); init(); for(i=1; i<=m; i++) { scanf("%d %d", &a, &b); if( a == b ) continue; node *p = (node *)malloc(sizeof(node)); p->index = b; p->next = edge[a].next; edge[a].next = p; } while( i=check() ) tarjan(i); for(i=1; i<=n; i++) { node *p = edge[i].next; while( p != NULL ) { if( belong[i] != belong[p->index]) out[belong[i]]++ ; p = p->next; } } int minNum = INF, ans = 0; for(i=1; i<=cnt; i++) { if(out[i] == 0) { if(minNum != INF) { minNum = 0; break; } minNum = size[i] ; } } printf("%d\n", minNum); return 0; }