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

受歡迎的牛——Tarjan

每一頭牛的願望就是變成一頭最受歡迎的牛。現在有 N 頭牛,給你 M 對整數(A,B),表示牛A認為牛B受歡迎。這種關係是具有傳遞性的,如果 A 認為 B 受歡迎,B 認為 C 受歡迎,那麼牛A也認為牛C受歡迎。你的任務是求出有多少頭牛被所有的牛認為是受歡迎的。
輸入格式:
第一行兩個數 N,M 。
接下來 M 行,每行兩個數 A,B,意思是 A 認為 B 是受歡迎的(給出的資訊有可能重複,即有可能出現多個 A,B)
輸出格式:
輸出一個整數,即有多少頭牛被所有的牛認為是受歡迎的。如果沒有滿足這種條件的情況,輸出“0”。
樣例輸入:
3 3
1 2
2 1
2 3
樣例輸出:


1
樣例說明:
只有牛 3 是受到所有牛歡迎的。
資料範圍:
10% 的資料:N≤20;M≤50
30% 的資料:N≤1000;M≤20000
70% 的資料:N≤5000;M≤50000
100% 的資料:N≤10000;M≤50000
題目分析
Tarjan模板題。只需縮點後記錄出度,當且僅當只有一個出度為0的點(實際可能是一個強連通分量),存在最受歡迎的牛,個數為強連通分量的大小。否則,沒有最受歡迎的牛,輸出0。
注:不懂Tarjan的可以看我的講解:http://blog.csdn.net/qianguch/article/details/54710272
附程式碼

#include<iostream>
#include<cstring>
#include<string> #include<cstdlib> #include<ctime> #include<queue> #include<iomanip> #include<cctype> #include<set> #include<map> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn=1e4+10; const int
maxm=5e4+10; int top,tot,n,m,times,cnt,dfn[maxn],low[maxn]; int nxt[maxm],to[maxm],first[maxn],stack[maxn]; int pd[maxn],num[maxn],x,y,du[maxn],sum,bh; bool vis[maxn],insta[maxn]; void create(int x,int y) { tot++; nxt[tot]=first[x]; first[x]=tot; to[tot]=y; } void dfs(int u) { times++; dfn[u]=times; low[u]=times; vis[u]=true; insta[u]=true; stack[top++]=u; for(int e=first[u];e;e=nxt[e]) { if(vis[to[e]]==false) { dfs(to[e]); low[u]=min(low[u],low[to[e]]); } else if(insta[to[e]]==true) low[u]=min(low[u],dfn[to[e]]); } if(low[u]==dfn[u]) { cnt++; while(top>=1&&stack[top]!=u) { top--; insta[stack[top]]=false; pd[stack[top]]=cnt; num[cnt]++;//記錄每個強連通分量的大小 } } } int main() { //freopen("lx.in","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); create(x,y); } for(int i=1;i<=n;i++) if(vis[i]==false) dfs(i); for(int i=1;i<=n;i++) for(int e=first[i];e;e=nxt[e]) if(pd[i]!=pd[to[e]]) du[pd[i]]++;//計算出度 for(int i=1;i<=cnt;i++) { if(du[i]==0)//看有多少個出度為0 { sum++; bh=i; } } if(sum==1) printf("%d",num[bh]); else printf("0"); return 0; }