码迷,mamicode.com
首页 > 其他好文 > 详细

poj2186 Popular Cows

时间:2017-01-30 12:30:31      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:连通   cst   main   names   std   cto   有向图   mem   set   

题意:

给定一个有向图,求有多少个顶点是由任何顶点出发都可达的。
顶点数<= 10,000,边数 <= 50,000

思路:

Korasaju算法把图进行强连通分量分解,在分解的同时得到各个强连通分量拓扑序。唯一可能成为解的就是拓扑序最后的强连通分量,最后再检查这个强连通分量是否能从各个顶点均可达即可。

实现:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 vector<int> G[10005], G_t[10005], res;
 8 int n, m, x, y, cmp[10005];
 9 bool vis[10005];
10 void dfs(int x)
11 {
12     vis[x] = true;
13     for (int i = 0; i < G[x].size(); i++)
14     {
15         if (!vis[G[x][i]])
16             dfs(G[x][i]);
17     }
18     res.push_back(x);
19 }
20 
21 void rdfs(int x, int k)
22 {
23     vis[x] = true;
24     cmp[x] = k;
25     for (int i = 0; i < G_t[x].size(); i++)
26     {
27         if (!vis[G_t[x][i]])
28         {
29             rdfs(G_t[x][i], k);
30         }
31     }
32 }
33 
34 int main()
35 {
36     while (cin >> n >> m)
37     {
38         for (int i = 1; i <= n; i++)
39         {
40             G[i].clear();
41             G_t[i].clear();
42         }
43         res.clear();
44         for (int i = 0; i < m; i++)
45         {
46             scanf("%d %d", &x, &y);
47             G[x].push_back(y);
48             G_t[y].push_back(x);
49         }
50         memset(vis, 0, sizeof(vis));
51         for (int i = 1; i <= n; i++)
52         {
53             if (!vis[i])
54                 dfs(i);
55         }
56         memset(vis, 0, sizeof(vis));
57         int k = 0;
58         for (int i = res.size() - 1; i >= 0; i--)
59         {
60             if (!vis[res[i]])
61             {
62                 rdfs(res[i], k++);
63             }
64         }
65         int cnt = 0, tmp = 0;
66         for (int i = 1; i <= n; i++)
67         {
68             if (cmp[i] == k - 1)
69             {
70                 cnt++;
71                 tmp = i;
72             }
73         }
74         memset(vis, 0, sizeof(vis));
75         rdfs(tmp, 0);
76         for (int i = 1; i <= n; i++)
77         {
78             if (!vis[i])
79             {
80                 cnt = 0;
81                 break;
82             }
83         }
84         printf("%d\n", cnt);
85     }
86     return 0;
87 }

总结:

有向图进行进行强连通分量分解并缩点之后可以得到一个DAG。

如果有多于一个出度为0的缩点则解为0。

 

poj2186 Popular Cows

标签:连通   cst   main   names   std   cto   有向图   mem   set   

原文地址:http://www.cnblogs.com/wangyiming/p/6357988.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!