標籤:scanf ios name 訪問 包含 int popular 思路 return
題目連結:http://poj.org/problem?id=2186
題目大意:
每一頭牛的願望就是變成一頭最受歡迎的牛。現在有N頭牛,給你M對整數(A,B),表示牛A認為牛B受歡迎。 這種關係是具有傳遞性的,如果A認為B受歡迎,B認為C受歡迎,那麼牛A也認為牛C受歡迎。你的任務是求出有多少頭牛被所有的牛認為是受歡迎的。
解題思路:假設有兩頭牛A和B都被其他所有牛認為是紅人,那麼顯然,A被B認為是紅人,B也被A認為是紅人,即存在一個包含A、B兩個頂點的圈,或者說,A、B同屬於一個強聯通分量。所以如果有一頭牛被其他所有牛認為是紅人,那麼其所屬的強聯通分量內的所有牛都被其他所有牛認為是紅人。我們把圖進行強聯通分量分解後,至多有一個強聯通分量滿足題目的條件。做法: 先用tarjan求出每個強連通分量,再縮點,統計每個點的出度,如果有且只有1個出度為0的點,就輸出這個點包含的節點數,否則輸出0。代碼
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #include<stack> 7 using namespace std; 8 const int N=1e4+5; 9 10 int cnt,num;11 int dfn[N],low[N],fa[N],sze[N],outdeg[N];12 stack<int>sk;13 vector<int>v[N];14 15 void tarjan(int u){16 dfn[u]=low[u]=++cnt;17 sk.push(u);18 for(int i=0;i<v[u].size();i++){19 int t=v[u][i];20 if(!dfn[t]){ //點t未被訪問21 tarjan(t);22 low[u]=min(low[u],low[t]);23 }24 else if(!fa[t]) low[u]=min(low[u],dfn[t]); //點t已被訪問,且t還在棧中25 }26 if(low[u]==dfn[u]){27 num++;28 while(1){29 int t=sk.top();30 sk.pop();31 fa[t]=num; //縮點操作,將這些點都歸為點num32 sze[num]++;33 if(t==u) break;34 }35 }36 }37 38 int main(){39 int n,m;40 scanf("%d%d",&n,&m);41 for(int i=1;i<=m;i++){42 int a,b;43 scanf("%d%d",&a,&b);44 v[a].push_back(b);45 }46 for(int i=1;i<=n;i++){47 if(!dfn[i]) tarjan(i);48 }49 for(int i=1;i<=n;i++){50 for(int j=0;j<v[i].size();j++){51 int t=v[i][j];52 if(fa[t]!=fa[i]) outdeg[fa[i]]++;53 }54 }55 //縮點後,出度為0的點只能有一個,否則不符合條件輸出056 int ans=0;57 for(int i=1;i<=num;i++){58 if(!outdeg[i]){59 if(ans>0){60 puts("0");61 return 0;62 }63 ans=sze[i];64 }65 }66 printf("%d\n",ans);67 return 0;68 }
POJ 2186 Popular Cows(強聯通分量)