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 }