题意:一个联通的无向图, 对于每一条边, 若删除该边后存在两点不可达,则输出这两个点, 如果存在多个则输出第一个点尽可能大,第二个点尽可能小的。 不存在输出0 0
首先 若删除某一条边后存在多个联通分量则该边一定是桥, 那么我们可以先处理出所有的桥,然后把所有双联通分量缩点,缩点之后就变成了一棵树。
而树上的每一条边都是一个桥, 考虑每条边的输出,删除某一边后肯定会出现两个联通分量, 需要记录两个联通分量中最大的点max1 max2, 如果max1!=n 则答案就是max1 max1+1否则max2 max2+1
现在的问题就转化为了如何求 不包含n的联通分量的最大值,因为两个联通分量肯定有一个联通分量的最大值为n, 所以 我们可以从包含n这个点的联通分量开始DFS, 每次遍历后更新一下,此时子树的最大值就是答案。
orz,第一次学习双联通分量。
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 void init () { 14 memset(isBridge, false, sizeof (isBridge)); 15 memset(pre, 0, sizeof (pre)); 16 memset(low, 0, sizeof (low)); 17 clk = 0; 18 for (int i = 0; i < MAXN; i++) { 19 G[i].clear(); 20 } 21 } 22 void DFS (int u, int pa) { 23 int lowu = pre[u] = ++clk; 24 for (int i = 0; i < G[u].size(); i++) { 25 pii e = G[u][i]; 26 int v = e.first; 27 int idx = e.second; 28 if (!pre[v]) { 29 DFS(v, u); 30 lowu = min(lowu, low[v]); 31 if (low[v] > pre[u]) { 32 isBridge[idx] = true; 33 } 34 } else if (pre[v] < pre[u] && v != pa) { 35 lowu = min(lowu, pre[v]); 36 } 37 } 38 low[u] = lowu; 39 } 40 void DFS2(int u, int pa) { 41 vis[u] = true; 42 maxv[u] = u; 43 newIdx[u] = IDX; 44 for (int i = 0; i < G[u].size(); i++) { 45 pii e = G[u][i]; 46 int v = e.first; 47 int idx = e.second; 48 if (!isBridge[idx] && v != pa && !vis[v]) { 49 DFS2(v, u); 50 maxv[u] = max(maxv[u], maxv[v]); 51 } 52 } 53 } 54 void BCC_Bridge() { 55 DFS(1, -1); 56 memset(vis, false, sizeof (vis)); 57 IDX = 0; 58 for (int i = 1; i <= n; i++) { 59 if (!vis[i]) { 60 IDX++; 61 DFS2(i, -1); 62 } 63 } 64 for (int i = 1; i <= n; i++) { 65 G[i].clear(); 66 } 67 for (int i = 0; i < m; i++) { 68 if (isBridge[i]) { 69 int u = newIdx[U[i]], v = newIdx[V[i]]; 70 G[u].push_back(make_pair(v, i)); 71 G[v].push_back(make_pair(u, i)); 72 } 73 } 74 } 75 void solve (int u, int pa) { 76 pre[u] = ++clk; 77 ans[u] = newMax[u]; 78 for (int i = 0; i < G[u].size(); i++) { 79 int v = G[u][i].first; 80 if (v != pa) { 81 solve(v, u); 82 ans[u] = max(ans[u], ans[v]); 83 } 84 85 } 86 } 87 int main() { 88 int T; 89 scanf ("%d", &T); 90 while (T--) { 91 init(); 92 scanf ("%d%d", &n, &m); 93 for (int i = 0; i < m; i++) { 94 int u, v; 95 scanf ("%d%d", &u, &v); 96 U[i] = u, V[i] = v; 97 G[u].push_back(make_pair(v, i)); 98 G[v].push_back(make_pair(u, i)); 99 } 100 BCC_Bridge(); 101 for (int i = 1; i <= n; i++) { 102 newMax[newIdx[i]] = maxv[i]; 103 } 104 int u; 105 for (u = 1; u <= n; u++) { 106 if (newMax[u] == n) { 107 break; 108 } 109 } 110 memset(pre, 0, sizeof pre); 111 clk = 0; 112 solve (u, 0); 113 for (int i = 0; i < m; i++) { 114 int u = newIdx[U[i]], v = newIdx[V[i]]; 115 if (u == v) { 116 printf("0 0 "); 117 } else { 118 if (pre[u] < pre[v]) { 119 swap(u, v); 120 } 121 printf("%d %d ", ans[u], ans[u]+1); 122 } 123 } 124 } 125 return 0; 126 }