题目链接: http://poj.org/problem?id=2186
题目大意:
给定一个n,m( 1<=n<=10000, 0<=m<=50000 )代表n头牛,m个关系,然后是m行,每行一个u,v代表 牛u认为牛v是popular的, 问有多少头牛被其他所有牛认为是popular的;
分析:
Tarjan缩点后,dfs扫描处理出每个强连通分量(SCC)的度数即可,关键是结论。
这题的答案应该是出度 out[i] == 0 的SCC的个数必须为1。
(开始我考虑好多情况,唯一漏掉的情况在我下载USACO的数据后被我发现了;)
代码:
POJ 2186
1 /*2186 Accepted 728K 79MS C++ 2618B 2012-04-18 19:09:52*/ 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <iostream> 6 #include <algorithm> 7 #include <vector> 8 using namespace std; 9 10 #define mpair make_pair 11 #define pii pair<int,int> 12 #define MM(a,b) memset(a,b,sizeof(a)); 13 typedef long long lld; 14 typedef unsigned long long u64; 15 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;} 16 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;} 17 #define maxn 10020 18 19 int n,m,top; 20 struct Edge{ 21 int v; 22 Edge *next; 23 } *adj[maxn], edge[50010]; 24 void Addedge(int u,int v){ 25 Edge *p= &edge[++top]; 26 p->v= v; 27 p->next= adj[u]; 28 adj[u]= p; 29 } 30 31 int Bcnt, Top, Index; 32 int c[maxn], belong[maxn]; 33 int stack[maxn], dfn[maxn], low[maxn]; 34 bool instack[maxn]; 35 36 void Tarjan(int u){ 37 instack[u]= 1; 38 stack[++Top]= u; 39 dfn[u]= low[u]= ++Index; 40 for(Edge *p= adj[u];p;p= p->next){ 41 int v= p->v; 42 if( !dfn[v] ){ 43 Tarjan( v ); 44 up_min( low[u], low[v] ); 45 } 46 else if( instack[v] ) 47 up_min( low[u], dfn[v] ); 48 } 49 if( low[u]==dfn[u] ){ 50 Bcnt++; 51 c[Bcnt]= 0; /// Init; 52 int v; 53 do{ 54 v= stack[Top--]; 55 instack[v]= 0; 56 belong[v]= Bcnt; 57 c[Bcnt]++; 58 }while( u!=v ); 59 } 60 } 61 62 bool vis[maxn]; 63 int out[maxn]; 64 void dfs(int u){ 65 vis[u]= 1; 66 for(Edge *p= adj[u];p;p= p->next){ 67 int v= p->v; 68 if( belong[v] != belong[u] ){ 69 out[ belong[u] ]++; 70 } 71 if( !vis[v] ) 72 dfs( v ); 73 } 74 } 75 76 int main() 77 { 78 while(scanf("%d%d", &n, &m)!=EOF){ 79 top= 0; 80 MM( adj, 0 ); 81 int i, u, v; 82 for(i=1;i<=m;++i){ 83 scanf("%d%d", &u, &v); 84 Addedge( u, v ); 85 } 86 if( 1==n ){ 87 puts("0"); 88 continue; 89 } 90 91 Bcnt= Top= Index= 0; 92 for(i=1;i<=n;++i) dfn[i]= low[i]= instack[i]= 0; 93 for(i=1;i<=n;++i){ 94 if( !dfn[i] ) 95 Tarjan( i ); 96 } 97 98 if( Bcnt==1 ) printf("%d\n", n); 99 else{ 100 fill( out+1, out+1+Bcnt, 0 ); 101 fill( vis+1, vis+1+n, 0 ); 102 for(i=1;i<=n;++i) 103 if( !vis[i] ) 104 dfs( i ); 105 106 int c2=0, t; 107 for(i=1;i<=Bcnt;++i) 108 if( out[i]==0 ){ 109 c2++; t=i; 110 } 111 if( c2==1 ) printf("%d\n", c[t]); 112 else puts("0"); 113 } 114 } 115 }