UVA-10765 Doves and bombs 【双连通分量】

题目链接:https://vjudge.net/problem/UVA-10765

题目大意:一个无向图中,求去掉每个点后的连通分量的数量。

 

题解:

这题实际上是求割顶,记录一下割顶的子孙当中反向边不在它之上的连通分量数量,最后加上图初始的连通分量数量。

 

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define M(a, b) memset(a, b, sizeof(a))
 4 #define INF 0x3f3f3f3f
 5 const int N = 1e5 + 5;
 6 int pre[N], dfs_clock, tot;
 7 vector<int> G[N];
 8 struct Node {
 9     int id, val;
10 
11     bool operator < (const Node &rhs) const {
12         if (rhs.val == val) return id < rhs.id;
13         return val > rhs.val;
14     }
15 };
16 vector<Node> ans;
17 
18 int dfs(int u, int fa) {
19     int lowu = pre[u] = ++dfs_clock;
20     int child = 0, num = 0;
21     for (int i = 0; i < G[u].size(); ++i) {
22         int v = G[u][i];
23         if (v == fa) continue;
24         if (!pre[v]) {
25             ++child;
26             int lowv = dfs(v, u);
27             lowu = min(lowu, lowv);
28             if (lowv >= pre[u]) ++num;
29         }
30         else lowu = min(lowu, pre[v]);
31     }
32     if (fa == -1 && child == 1) num = 0;
33     ans.push_back(Node{u, num});
34     return lowu;
35 }
36 
37 void find_bcc(int n) {
38     M(pre, 0); dfs_clock = tot = 0;
39     ans.clear();
40     for (int i = 0; i < n; ++i)
41         if (!pre[i]) {
42             ++tot;
43             dfs(i, -1);
44         }
45     sort(ans.begin(), ans.end());
46 }
47 
48 int main() {
49     int n, m;
50     while (~scanf("%d%d", &n, &m), n && m) {
51         for (int i = 0; i < n; ++i) G[i].clear();
52         int u, v;
53         while (true) {
54             scanf("%d%d", &u, &v);
55             if (u == -1 && v == -1) break;
56             G[u].push_back(v);
57             G[v].push_back(u);
58         }
59         find_bcc(n);
60         for (int i = 0; i < m; ++i) printf("%d %d\n", ans[i].id, ans[i].val+tot);
61         printf("\n");
62     }
63 
64     return 0;
65 }

 

posted @ 2017-04-15 20:45  Robin!  阅读(243)  评论(0编辑  收藏  举报