POJ2186 Popular Cows Kosaraju
阿新 • • 發佈:2018-12-30
題目大意是:在一個牧群中,有N個奶牛,給定M對關係(A,B)表示A仰慕B,而且仰慕關係有傳遞性,問被所有奶牛(除了自己)仰慕的奶牛個數
因為仰慕關係具有傳遞性,因此在一個強連通分量中,每個奶牛都被分量中的其他奶牛膜拜,而且也膜拜著分量中的其他奶牛,這種互相膜拜的場景在現實生活中也是經常存在的,因此,本題可以將強連通分量縮點,並構造新圖,最後做一次掃描,統計出度為0的點的個數,如果正好為1,表示這個強連通分量(可能是一個點,也可能是多個點)中的奶牛都符合條件,輸出其中的個數即可。
如果不唯一,顯然就沒有奶牛符合被所有奶牛膜拜的條件了。
#include<iostream> #include<vector> #include<cstring> #include<queue> #define INF 99999999 using namespace std; int n, m; int num[10005];//第i個強連通分量包含的個數 bool P[10005];//DFS判重 int flag[10005];//該點是屬於第幾個強連通分量 vector<int> v[10005];//正向圖 vector<int> rv[10005];//反向圖 vector<int> s; int cnt; void dfs1(int x){ P[x] = 1; for (int i = 0; i < v[x].size(); i++) if (!P[v[x][i]]) dfs1(v[x][i]); s.push_back(x); } void dfs2(int x){ flag[x] = cnt; num[cnt]++; P[x] = 1; for (int i = 0; i < rv[x].size(); i++) if (!P[rv[x][i]]) dfs2(rv[x][i]); } void Kosaraju(){ memset(P, 0, sizeof(P)); for (int i = 1; i <= n; i++) { for (int j = 0; j < v[i].size(); j++){//檢查強連通分量是否有出度,有就對應的P[i]=1 int w = v[i][j]; if (flag[i] != flag[w]) P[flag[i]] = 1;//這個強連通分量標記為1 } } int ans; int t = 0; for (int i = 1; i <= cnt; i++){//檢查有幾個強連通分量的出度為0 if (!P[i]){ ans = i; t++; } } if (t == 1)//如果只有一個強連通分量的入度為0,則輸出應的tree_n[i]為要的答案,否則沒有 printf("%d\n", num[ans]); else printf("0\n"); } int main(){ int a, b; scanf("%d%d", &n, &m); for (int i = 0; i < m; i++){ scanf("%d%d", &a, &b); v[a].push_back(b); rv[b].push_back(a); } for (int i = 1; i <= n; i++) if (!P[i]) dfs1(i); memset(P, 0, sizeof(P)); memset(num, 0, sizeof(num)); cnt = 0; for (int i = s.size() - 1; i >= 0; i--){ if (!P[s[i]]){ cnt++; dfs2(s[i]); } } Kosaraju(); return 0; }