HDU5409---CRB and Graph 2015多校 双联通分量缩点

题意:一个联通的无向图, 对于每一条边, 若删除该边后存在两点不可达,则输出这两个点, 如果存在多个则输出第一个点尽可能大,第二个点尽可能小的。 不存在输出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\n");
117             } else {
118                 if (pre[u] < pre[v]) {
119                     swap(u, v);
120                 }
121                 printf("%d %d\n", ans[u], ans[u]+1);
122             }
123         }
124     }
125     return 0;
126 }

 

posted @ 2015-08-21 19:37  PlasticSpirit  阅读(1070)  评论(0编辑  收藏  举报