1. 程式人生 > >HAOI2006 受歡迎的牛

HAOI2006 受歡迎的牛

思路 sed mes row spa all define std 連通性

HAOI2006 】受歡迎的牛

Description

每一頭牛的願望就是變成一頭最受歡迎的牛。現在有N頭牛,給你M對整數(A,B),表示牛 A 認為牛 B受歡迎。這種關系是具有傳遞性的,如果A認為B受歡迎,B認為C受歡迎,那麽牛A也認為牛C受歡迎。你的任務是求出有多少頭牛被所有的牛認為是受歡迎的。

Input

第1行兩個整數N,M;
接下來M行,每行兩個數A,B,意思是A認為B是受歡迎的(給出的信息有可能重復,即有可能出現多個A,B)

Output

一個數,即有多少頭牛被所有的牛認為是受歡迎的。

Sample Input

3 3

1 2

2 1

2 3

Sample Output

1

Hint

10%的數據N<=20,M<=50
30%的數據N<=1000,M<=20000
70%的數據N<=5000,M<=50000
100%的數據N<=10000,M<=50000

Source

HAOI2006
圖論,連通性

本來寒假已經 AC 過一次,結果POJ數據增強了,結果 WA ,看不出哪裏萎了,於是重新碼了一遍。

思路還是很清晰的:tarjan 縮點成 DAG 然後判斷是否只有一個強連通分量出度為

0 ,如果是,則輸出size,否則輸出 0

證明:若強連通分量X有出邊,則出邊所指向的點必不喜歡X(若喜歡則與X為同一強連通分量),則X不是答案。存在兩個或以上的強連通分量沒有出邊,則他們互相不喜歡,所以沒有答案。

技術分享
  1 #include <map>
  2 #include <set>
  3 #include <cmath>
  4 #include <ctime>
  5 #include <queue>
  6 #include <stack>
  7 #include <cstdio>
  8
#include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 #define re register 16 #define ll long long 17 #define file(a) freopen(a".in","r",stdin); freopen(a".out","w",stdout); 18 19 inline int gi() 20 { 21 bool b=0; int r=0; char c=getchar(); 22 while(c<0 || c>9) { if(c==-) b=!b; c=getchar(); } 23 while(c>=0 && c<=9) { r=r*10+c-0; c=getchar(); } 24 if(b) return -r; return r; 25 } 26 27 const int inf = 1e9+7, N = 1e4+7, M = 5e4+7; 28 int n,m,num,f[N],dfn[N],low[N],cnt,siz[N],bl[N],hd[N],sum; 29 bool b[N]; 30 struct node 31 { 32 int nx,to; 33 }; node da[M],dd[M]; 34 stack <int> z; 35 36 inline int Min (int a, int b) 37 { 38 return a < b? a : b; 39 } 40 41 inline void add (int fr, int to) 42 { 43 da[++num].to = to, da[num].nx = f[fr], f[fr] = num; 44 } 45 46 inline void link (int fr, int to) 47 { 48 dd[++sum].to = to, dd[sum].nx = hd[fr], hd[fr] = sum; 49 } 50 51 inline void tarjan (int o) 52 { 53 re int i,to; 54 dfn[o] = low[o] = ++num; 55 z.push(o); b[o] = 1; 56 for (i=f[o]; i; i=da[i].nx) 57 { 58 to = da[i].to; 59 if (!dfn[to]) 60 { 61 tarjan (to); low[o] = Min (low[o], low[to]); 62 } 63 else if (b[to]) low[o] = Min (low[o], dfn[to]); 64 } 65 if (dfn[o] == low[o]) 66 { 67 ++cnt; 68 do 69 { 70 to = z.top(); z.pop(); b[to] = 0; 71 bl[to] = cnt; siz[cnt]++; 72 } 73 while (to != o); 74 } 75 } 76 77 int main () 78 { 79 n = gi(), m = gi(); 80 re int i,j,to,x,y,ans=0; bool fg; 81 for (i=1; i<=m; i++) 82 { 83 x = gi(), y = gi(); 84 add (x, y); 85 } 86 num = 0; 87 for (i=1; i<=n; i++) if(!dfn[i]) tarjan(i); 88 for (i=1; i<=n; i++) 89 for (j=f[i]; j; j=da[j].nx) 90 { 91 to = da[j].to; x = bl[i]; y = bl[to]; 92 if (x != y) link (x, y); 93 } 94 for (i=1; i<=cnt; i++) 95 { 96 fg = 1; 97 for (j=hd[i]; j; j=dd[j].nx) if (dd[j].to != i) fg = 0; 98 if (fg) 99 { 100 if(!ans) ans = siz[i]; 101 else 102 { 103 puts ("0"); 104 return 0; 105 } 106 } 107 } 108 printf ("%d\n",ans); 109 return 0; 110 }
View Code

HAOI2006 受歡迎的牛