hdu 5409 CRB and Graph(边双联通分量)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 5409 CRB and Graph(边双联通分量)相关的知识,希望对你有一定的参考价值。
题意:
给一个图一些边,保证图连通
问对于每条边,如果去除该边后使得图中一些点不连通。设这些点(u,v),要求使u尽量小,v尽量大,输出这样的(u,v)。否则输出0 0。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int MAXN = 1e5 + 1; 4 typedef pair <int, int>pii; 5 vector<pii>G[MAXN]; 6 bool isBridge[MAXN]; 7 int clk, pre[MAXN], low[MAXN]; 8 int IDX, maxv[MAXN], newIdx[MAXN], newMax[MAXN]; 9 int U[MAXN], V[MAXN]; 10 int ans[MAXN]; 11 bool vis[MAXN]; 12 int n, m; 13 14 void init () { 15 memset(isBridge, false, sizeof (isBridge)); //记录桥 16 memset(pre, 0, sizeof (pre)); //记录的第一次访问的时间戳 17 memset(low, 0, sizeof (low)); //本身及其子节点能回到的最早的祖先的pre值 18 clk = 0; //时间戳 19 for (int i = 0; i < MAXN; i++) { 20 G[i].clear(); 21 } 22 } 23 24 void DFS (int u, int pa) { 25 int lowu = pre[u] = ++clk; 26 for (int i = 0; i < G[u].size(); i++) { 27 pii e = G[u][i]; 28 int v = e.first; 29 int idx = e.second; 30 if (!pre[v]) { 31 DFS(v, u); 32 lowu = min(lowu, low[v]); 33 if (low[v] > pre[u]) { 34 isBridge[idx] = true; 35 } 36 } else if (pre[v] < pre[u] && v != pa) { 37 //是反向边更新lowu 38 lowu = min(lowu, pre[v]); 39 } 40 } 41 low[u] = lowu; //更改low[u] 42 } 43 44 void DFS2(int u, int pa) { 45 vis[u] = true; 46 maxv[u] = u; 47 newIdx[u] = IDX; 48 for (int i = 0; i < G[u].size(); i++) { 49 pii e = G[u][i]; 50 int v = e.first; 51 int idx = e.second; 52 if (!isBridge[idx] && v != pa && !vis[v]) { 53 DFS2(v, u); 54 maxv[u] = max(maxv[u], maxv[v]); 55 } 56 } 57 } 58 59 void BCC_Bridge() { 60 DFS(1, -1); //记录桥 61 memset(vis, false, sizeof (vis)); 62 IDX = 0; 63 for (int i = 1; i <= n; i++) { 64 if (!vis[i]) { 65 IDX++; 66 DFS2(i, -1); //缩点 67 } 68 } 69 //重新记录缩后的点 70 for (int i = 1; i <= n; i++) { 71 G[i].clear(); 72 } 73 for (int i = 0; i < m; i++) { 74 if (isBridge[i]) { 75 int u = newIdx[U[i]], v = newIdx[V[i]]; 76 G[u].push_back(make_pair(v, i)); 77 G[v].push_back(make_pair(u, i)); 78 } 79 } 80 } 81 82 void solve (int u, int pa) { 83 pre[u] = ++clk; 84 ans[u] = newMax[u]; 85 for (int i = 0; i < G[u].size(); i++) { 86 int v = G[u][i].first; 87 if (v != pa) { 88 solve(v, u); 89 ans[u] = max(ans[u], ans[v]); 90 } 91 } 92 } 93 94 int main() { 95 int T; 96 scanf ("%d", &T); 97 while (T--) { 98 init(); //进行初始化 99 scanf ("%d%d", &n, &m); 100 for (int i = 0; i < m; i++) { 101 int u, v; 102 scanf ("%d%d", &u, &v); 103 U[i] = u, V[i] = v; 104 G[u].push_back(make_pair(v, i)); 105 G[v].push_back(make_pair(u, i)); 106 } 107 BCC_Bridge(); 108 for (int i = 1; i <= n; i++) { 109 newMax[newIdx[i]] = maxv[i]; 110 } 111 int u; 112 for (u = 1; u <= n; u++) { 113 if (newMax[u] == n) { 114 break; 115 } 116 } 117 memset(pre, 0, sizeof pre); 118 clk = 0; //重新定义时间戳 119 solve (u, 0); 120 for (int i = 0; i < m; i++) { 121 int u = newIdx[U[i]], v = newIdx[V[i]]; 122 if (u == v) { 123 printf("0 0\n"); 124 } else { 125 if (pre[u] < pre[v]) { 126 swap(u, v); 127 } 128 printf("%d %d\n", ans[u], ans[u]+1); 129 } 130 } 131 } 132 return 0; 133 }
以上是关于hdu 5409 CRB and Graph(边双联通分量)的主要内容,如果未能解决你的问题,请参考以下文章
HDU - 5411 CRB and Puzzle 矩阵快速幂