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

bzoj1051 [HAOI2006]受歡迎的牛

time ostream tro 2個 amp pre logs esc iostream

1051: [HAOI2006]受歡迎的牛

Time Limit: 10 Sec Memory Limit: 162 MB

Description

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

Input

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

Output

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

Sample Input

3 3
1 2
2 1
2 3

Sample Output

1

HINT

100%的數據N<=10000,M<=50000 Tip:   這題還是比較經典的tarjan縮點模板題;   如果A認為B是受歡迎的,那麽連A->B;   將整個圖縮點,變成了一個有向無環圖;   如果縮點後的圖中點的出度=0的點數大於2個,則沒有答案,沒有任何一頭奶牛能被所有奶牛認可;                   1個,則答案即那個強連通分量裏的點的數量; Code
#include<cstdio>
#include<algorithm>
#include
<iostream> #include<cstring> #define MAXN 100008 using namespace std; int n,m,hh[MAXN],head[MAXN],vet[MAXN],next[MAXN],tot,dfn[MAXN],low[MAXN],color[MAXN]; int tot1,num[MAXN],str[MAXN],cnt,boo[MAXN],top,belong[MAXN],tim; void add(int x,int y){ tot++; hh[tot]=x; next[tot]=head[x]; head[x]
=tot; vet[tot]=y; } void tarjan(int u){ tim++; dfn[u]=low[u]=tim; boo[u]=color[u]=1; str[++top]=u; for(int i=head[u];i!=-1;i=next[i]){ int y=vet[i]; if(color[y]==0){ tarjan(y); low[u]=min(low[u],low[y]); }else{ if(boo[y]) low[u]=min(low[u],dfn[y]); } } color[u]=2; if(dfn[u]==low[u]){ cnt++; int v; do{ v=str[top--]; belong[v]=cnt; boo[v]=1; }while(v!=u&&top>0); } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) head[i]=-1; for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); } for(int i=1;i<=n;i++) if(!dfn[i]){ tarjan(i); } for(int i=1;i<=tot;i++){ if(belong[hh[i]]!=belong[vet[i]]){ num[belong[hh[i]]]++; } } int ans=0,flag; for(int i=1;i<=cnt;i++){ if(num[i]==0){ ans++; if(ans>1){ printf("0"); return 0; } flag=i; } } if(ans==1){ int res=0; for(int i=1;i<=n;i++) if(belong[i]==flag) res++; printf("%d",res); }else{ printf("0"); } }

  

bzoj1051 [HAOI2006]受歡迎的牛