POJ2186Popular Cows(强连通分量分解模板)

来源:互联网 发布:linuxmint与ubuntu 编辑:程序博客网 时间:2024/04/26 07:20
Popular Cows
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 33426 Accepted: 13615

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. 

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. 

Output

* Line 1: A single integer that is the number of cows who are considered popular by every other cow. 

Sample Input

3 31 22 12 3

Sample Output

1

Hint

Cow 3 is the only cow of high popularity. 

Source

USACO 2003 Fall

题目大意:一共有n头牛,m条边,(x,y)意味着x崇拜y,问一共有多少头牛能够被所有牛都崇拜

解题思路:考虑到马上出去比赛和省赛,我就负责了图论的东西,这道题主要是用的是强连通分量分解的解法,强连通块指的是内部所有点都可以通过之间的有向边到达,多一个点少一个点都不可以

强连通分量分解的思路主要是两部分,每一部分都是DFS,但是每次DFS的目的不一样

第一次进行DFS的时候,按照要求建图,可以从任何一点开始遍历,当沿着有向边遍历到无法遍历的时候,开始回溯标记,同时把点放到vector中,意味着越接近子节点标记越小,然后接着遍历未标记的点,重复回溯标记,放到vector

第二次进行DFS的时候,按照要求反建图,从vector中,从标记最大的点开始遍历,每遍历到头之后,这意味着这些点组成了一个强连通块,之后再遍历那些未遍历的点

两次DFS就是强连通分量的全部,第一次DFS将所有的点排序,第二次DFS反向建图后生成强连通块

这道题除了以上的DFS以外,还有一些要考虑的东西,由于组成强连通块之后,成为最后那一个连通块的意味着他们是处在拓扑序的最后面,他们就是这道题中所谓的受到其他牛崇拜的牛,所以我们之后要查找有多少个牛属于最后一个强连通块,同时从中选择一个按照反建图DFS,若是从他能跑过所有点,意味着强连通块的所有都属于被崇拜的牛,反之不是

#include<iostream>    #include<cstdio>  #include<stdio.h>  #include<cstring>    #include<cstdio>    #include<climits>    #include<cmath>   #include<vector>  #include <bitset>  #include<algorithm>    #include <queue>  #include<map>  using namespace std;#define inf 9999999;vector<int> tu[10005], rtu[10005], qua;int vis[10005];int check[10005];int ans, sum, k,n, m;void dfs(int x){int i;for (i = 0; i < tu[x].size(); i++){if (!vis[tu[x][i]]){vis[tu[x][i]] = 1;dfs(tu[x][i]);}}qua.push_back(x);}void dfs1(int x){for (int i = 0; i < rtu[x].size(); i++){if (!vis[rtu[x][i]]){vis[rtu[x][i]] = 1;check[rtu[x][i]] = ans;dfs1(rtu[x][i]);}}}int main(){int i, x, y;cin >> n >> m;for (i = 1; i <= m; i++){cin >> x >> y;tu[x].push_back(y);rtu[y].push_back(x);}memset(vis, 0, sizeof(vis));for (i = 1; i <= n; i++){if (!vis[i]){vis[i] = 1;dfs(i);}}memset(vis, 0, sizeof(vis));ans = 0;for (i = qua.size() - 1; i >= 0; i--){if (!vis[qua[i]]){vis[qua[i]] = 1;ans++;check[qua[i]] = ans;dfs1(qua[i]);}}sum = k = 0;memset(vis, 0, sizeof(vis));for (i = 1; i <= n; i++){if (check[i] == ans){sum++;k = i;}}vis[k] = 1;dfs1(k);for (i = 1; i <= n; i++){if (!vis[i]){sum = 0;break;}}cout << sum << endl;}


0 0