zoukankan      html  css  js  c++  java
  • 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
    ");
    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 }
  • 相关阅读:
    fill 全解(转)
    解题报告 疯狂的馒头
    解题报告 报数
    解题报告 noi 2005 智慧珠游戏(BT 搜索)
    解题报告 跑步
    解题报告 Punch
    解题报告 纪念日
    解题报告 新兵站队
    转载:让理科生沉默,让文科生流泪的综合题
    解题报告 信号放大器
  • 原文地址:https://www.cnblogs.com/oneshot/p/4748840.html
Copyright © 2011-2022 走看看