Popular Cows//强连通分支Kosaraju加缩点
题目:
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 38415 | Accepted: 15658 |
Description
Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive, if A thinks B is popular and B thinks C is popular, then A will also think that C is
popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow.
popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow.
Input
* Line 1: Two space-separated integers, N and M
* Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.
* Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.
Output
* Line 1: A single integer that is the number of cows who are considered popular by every other cow.
Sample Input
3 3 1 2 2 1 2 3
Sample Output
1
Hint
Cow 3 is the only cow of high popularity.
思路:
代码:
#include <iostream> #include <vector> using namespace std; const int size = 1e4 + 1; vector<int> graph[size]; vector<int> reverse[size]; int order[size];//栈 int pos = 0;//用于order[]的索引 bool marked[size]; bool marked2[size]; int ans = 0;//连通分支数 int DAG[size];//分离强连通分量 int out[size];//DAG的出度,一共只有强连通分支数那么多个点 void init(int N)//初始化 { pos = ans = 0; for(int i = 1; i <= N; i++) { marked[i] = false; marked2[i] = false; graph[i].clear(); reverse[i].clear(); DAG[i] = 0; out[i] = 0; } } void dfsReverseOrder(int x) { marked[x] = true; for(int i = 0; i < reverse[x].size(); i++) { if(!marked[reverse[x][i]]) dfsReverseOrder(reverse[x][i]); } order[pos++] = x; } void dfs(int x) { DAG[x] = ans; marked2[x] = true; for(int i = 0; i < graph[x].size(); i++) { if(!marked2[graph[x][i]]) { dfs(graph[x][i]); } else if(DAG[graph[x][i]] != DAG[x])//和计算出度有关 out[ans] = 1; } } void Kosaraju(int N) { for(int i = 1; i <= N; i++) { if(!marked[i]) dfsReverseOrder(i); } pos--; for(; pos >= 0;pos--) { if(!marked2[order[pos]]) { dfs(order[pos]); ans++; } } } int main() { int N, M; int a, b; while(cin >> N >> M) { init(N); //输入 for(int i = 0; i < M; i++) { cin >> a >> b; graph[a].push_back(b); reverse[b].push_back(a); } Kosaraju(N); int count = 0; int flag; for(int i = 0; i < ans; i++)//找出度为0的强连通分支的个数 { if(out[i] == 0) { count++; flag = i; } } int num = 0; if(count == 1)//若只有一个出度为0的强连通分支 { for(int i = 1; i <= N; i++)//计算该强连通分支内点的个数 { if(DAG[i] == flag) num++; } printf("%d\n", num); } else printf("%d\n", 0); } return 0; }