1. 程式人生 > >【POJ2186 最受歡迎的牛】

【POJ2186 最受歡迎的牛】

poj class inline head line break div ext tarjan縮點

題目大意:

每一頭牛的願望就是變成一頭最受歡迎的牛。現在有N(1<=N<=10000)頭牛,給你M(1<=M<=50000)對整數(A,B),表示牛A認為牛B受歡迎。 這

種關系是具有傳遞性的,如果A認為B受歡迎,B認為C受歡迎,那麽牛A也認為牛C受歡迎。你的任務是求出有多少頭

牛被所有的牛認為是受歡迎的。

輸入格式:

  第一行輸入n,m

  下面m行每行輸入x,y表示x到y有一條邊

輸出格式:

  輸出受歡迎奶牛的數量

輸入樣例

  3 3
  1 2
  2 1
  2 3

輸出樣例

  1

題解

  先tarjan縮點,對於新建的圖中,出度為0的點如果只有一個,說明這個點(縮過)被所有奶牛歡迎。否則的話就不可能有

奶牛被所有的牛認為是受歡迎。

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<algorithm>
 6 struct nd1
 7 {
 8     int next,to;
 9 }    e1[150005];
10 int head[110005],out[110005],sc,cnt;
11 inline void insert(int u,int v)
12 {
13     e1[++cnt].next=head[u];
14 head[u]=cnt; 15 e1[cnt].to=v; 16 } 17 int time,s[110005],vis[110005],dfn[110005],low[110005],bl[110005],num[110005]; 18 int n,m; 19 inline void tarjan(int now) 20 { 21 dfn[now]=low[now]=++time; 22 s[++s[0]]=now;vis[now]=1; 23 for(int i=head[now];i;i=e1[i].next) 24 { 25 if(!dfn[e1[i].to])
26 { 27 tarjan(e1[i].to); 28 low[now]=std::min(low[now],low[e1[i].to]); 29 } 30 else if(vis[e1[i].to]) 31 low[now]=std::min(low[now],dfn[e1[i].to]); 32 } 33 if(dfn[now]==low[now]) 34 { 35 num[bl[now]=++sc]=1; 36 vis[now]=0; 37 while(s[s[0]]!=now) 38 { 39 vis[s[s[0]]]=0; 40 bl[s[s[0]]]=sc; 41 num[sc]++; 42 s[0]--; 43 } 44 s[0]--; 45 } 46 } 47 inline void rdeg() 48 { 49 for(int i=1;i<=n;i++) 50 for(int j=head[i];j;j=e1[j].next) 51 { 52 if(bl[i]!=bl[e1[j].to]) 53 out[bl[i]]++; 54 } 55 } 56 int main() 57 { 58 int u,v; 59 scanf("%d%d",&n,&m); 60 for(int i=1;i<=m;i++) 61 { 62 scanf("%d%d",&u,&v); 63 insert(u,v); 64 } 65 for(int i=1;i<=n;i++) 66 if(!dfn[i]) tarjan(i); 67 rdeg(); 68 int ans=0; 69 for(int i=1;i<=sc;i++) 70 { 71 if(!out[i] && !ans) ans=num[i]; 72 else if(!out[i] && ans!=0) 73 { 74 ans=-1; 75 break; 76 } 77 } 78 if(ans==-1) puts("0\n"); 79 else printf("%d\n",ans); 80 return 0; 81 }

【POJ2186 最受歡迎的牛】