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 }
时间: 2024-10-10 17:25:01

HDU5409---CRB and Graph 2015多校 双联通分量缩点的相关文章

poj3694 network(边双联通分量+lca+并查集)

题    目    传    送    们    在    这 题目大意 有一个由n个点和m条边组成的无向联通图. 现在有Q个操作,每次操作可以在点x,y之间连一条边. 问你每次操作后有多少个多少个桥(即删掉后就会使图不联通的边). 解题思路 根据边双联通的定义,我们知道将边双联通分量缩点后的图,其中的边即为桥. 我们将这个图缩点,就变成了一棵树. 而每次在两个不同的边双联通分量x,y之间加边后,就出现了一个包含x,y的环,其中原先这颗树上x,y的树上最短路径就不在是边. 所以对于每个x,y,我

hihocoder #1190 : 连通性&#183;四 点双联通分量

http://hihocoder.com/problemset/problem/1190?sid=1051696 先抄袭一下 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho从约翰家回到学校时,网络所的老师又找到了小Hi和小Ho. 老师告诉小Hi和小Ho:之前的分组出了点问题,当服务器(上次是连接)发生宕机的时候,在同一组的服务器有可能连接不上,所以他们希望重新进行一次分组.这一次老师希望对连接进行分组,并把一个组内的所有连接关联的服务器也视为这个组内

[HDOJ4738]Caocao&#39;s Bridges(双联通分量,割边,tarjan)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4738 给一张无向图,每一条边都有权值.找一条割边,使得删掉这条边双连通分量数量增加,求权值最小那条. 注意有重边,ACEveryDay里群巨给的意见是tarjan的时候记录当前点是从哪条边来的. 注意假如桥的权值是0的时候也得有一个人去炸…… 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7

UVA - 10765 Doves and bombs (双联通分量)

链接 :  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34798 给N个点的无向图并且联通,问删除每次一个点之后还剩多少联通分量. 找割顶 如果删除的是割顶 联通分量就会增加,否则还是1(因为原图是联通图),删除割顶之后 联通块的数目 就要看该割顶在几个双联通分量里出现过. #pragma comment(linker, "/STACK:10240000,10240000") #include <a

【POJ 2942】Knights of the Round Table(双联通分量+染色判奇环)

[POJ 2942]Knights of the Round Table(双联通分量+染色判奇环) Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 11661   Accepted: 3824 Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, an

BZOJ2730 矿场搭建 解题报告 点双联通分量

题意概述: 一张有向图,在其中设置一些关键点(即题目中的逃生出口),使得删除任意一个点之后其余点都可以到达至少一个关键点. 问至少需要设置多少中关键点,有多少种设置方法. 解析: 首先,这道题要求删掉一个点,不难想到这道题与割点有关.其次,删掉一个点其他点仍然可以到达关键点就可以想到是点双联通分量. 但是,问题关键是,真的需要在每一个点双联通分量中都设置一个关键点吗? 答案是否定的,因为如果一个双联通分量连接了两个或两个以上的割点,一个割点被删掉那么还可以通过另外的割点到达某个关键点,如上图,红

POJ 1515 双联通分量

点击打开链接 题意:给一个联通的无向图,然后问你将其中的边变为有向的,加边使其变成有向的联通图 思路:若无向图有双联通分量,那么这个分量里的元素可以变成有向图的强联通,这应该很好看出来,然后需要加的边是什么呢,就是这个图上的桥呗,是桥的话变成有向的就要加一条边,然后剩下的无向图的双联通分量可以用dfs搜一下,边搜边输出就可以了,将桥记录下来遇到桥的时候特殊处理一下,然后双联通分量里的边每一条只能走一次,将走得边和反向边标记一下就行了  PS:vector写这样反向边的真是麻烦 #include

HDU 4612 双联通分量+树的直径

点击打开链接 题意:给一个无向联通图,里面可能有重边,问添加一条边后,使得图中的桥最小,将桥的数量输出 思路:刚刚读完题,就有了思路去写,无非就是将联通图双联通分量后缩点,然后求一条最长的路,首尾相连,肯定将更多的桥包含使得这些桥不再是桥,很好想的题,但是错了20+什么鬼,md重边这么难处理,醉了~~~,之前的做法是将重边全部找出来,希望数据弱点水过去算了,TLE好样的,那么我们在处理桥的时候,也就是找桥的时候,如果是桥,我们将这条边标记一下,然后找所有边时加上就行了,在一个就是找树的直径,两次

HDU 4738 Caocao&#39;s Bridges(双联通分量+并查集)

大意:有n座岛和m条桥,每条桥上有w个兵守着,现在要派不少于守桥的士兵数的人去炸桥,只能炸一条桥,使得这n座岛不连通,求最少要派多少人去. 思路:我们就是要缩点后直接求桥上人的最少数量.(PS:1.注意图如果不联通直接输出0.2.如果图中的桥上人为0,个那么要让一个人去.3.重边的问题.这里可以忽略) #include<map> #include<queue> #include<cmath> #include<cstdio> #include<stac