Popular Cows POJ - 2186(题解)

原题

http://poj.org/problem?id=2186

题目大意

题目会给一个牛的有向图,A→B意味着A认为B流行,如果A→B,B→C,则A和B都认为C流行,要求求出这群牛中被所有牛认为流行的牛的数.

题目分析

这道题中会存在一些情况例如 A→B,B→C,C→A这种,就是A B C强连通,所以需要把这些强连通的点集压缩成一个点并进行拓扑排序,然后只要找序列中的最后一个点,用dfs检查一遍是否能跑遍全图,是则输出该点被压缩的数量,否则输出0.找强连通可以先用dfs扫一下有向图(确保所有点都被该dfs扫过),再将地图上的所有路反向,再用dfs从上次dfs的第一个开始,扫遍所有的点,这次每扫一次dfs都能求解出一个强连通分量,因为路方向后,只有强连通里的点不受影响,各个强连通分量都会被隔绝,因此可以找出所有的强连通分量.

代码

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <string>
 8 #include <utility>
 9 #include <queue>
10 #include <stack>
11 #include <map> 
12 const int INF=0x3f3f3f3f;
13 using namespace std;
14 
15 vector<int> G[10001],rG[10001]; //G是放输入边的,rG是放反向后的边的 
16 vector<int> vs; //用来存第一次dfs 点的遍历顺序 
17 bool vis[10001]; //检查点是否扫过 
18 int cmp[10001]; //表示拓扑排序中的序号 
19 
20 void add(int from,int to) //添加边 
21 {
22     G[from].push_back(to);
23     rG[to].push_back(from);
24 }
25 
26 void dfs(int s) //第一次dfs 
27 {
28     vis[s]=true;
29     for(int i=0;i<G[s].size();i++)
30     if(!vis[G[s][i]]) dfs(G[s][i]);
31     vs.push_back(s);
32 }
33 
34 void rdfs(int s,int k) //第二次dfs k是拓扑排序序号 
35 {
36     vis[s]=true;  
37     cmp[s]=k;  
38     for(int i=0;i<rG[s].size();i++)
39     if(!vis[rG[s][i]]) rdfs(rG[s][i],k);
40 }
41 
42 int main()
43 {
44     int n,m;
45     cin>>n>>m;
46     while(m--)
47     {
48         int a,b;
49         scanf("%d%d",&a,&b);
50         add(a,b);
51     } 
52     
53     for(int i=1;i<=n;i++)
54     if(!vis[i]) dfs(i);
55     
56     memset(vis,0,sizeof(vis));
57     int k=0;
58     
59     for(int i=vs.size()-1;i>=0;i--)
60     if(!vis[vs[i]]) rdfs(vs[i],k++);
61     
62     int u,ans=0; //找出拓扑序列最后一个点 
63     for(int i=1;i<=n;i++)
64     if(cmp[i]==k-1) u=i,ans++;
65 
66     //检查最后一个强连通分量上的一个点能否经过所有的点(即被所有牛认为流行) 
67     memset(vis,0,sizeof(vis));
68     rdfs(u,0);
69     for(int i=1;i<=n;i++)
70     if(!vis[i]) 
71     {
72         ans=0;
73         break;
74     }
75     cout<<ans<<endl;
76     return 0;
77 }

猜你喜欢

转载自www.cnblogs.com/VBEL/p/10497655.html
今日推荐