hdu2460-Network:边的双连通分量

题目大意:给出一个无向图以及Q次询问,每次询问增加一条无向边,要求输出增加这条边后剩余的桥的数目。

算法:类似于求割点的方法,先做一次dfs求出所有的桥,并且维护这棵dfs树,当一次询问加入一条边(a,b)之后,会在dfs上形成一个环,在这个环上的桥都变为非桥,这个环肯定经过a和b的LCA,此时我们只需在求LCA的过程中把经过的为桥的树边标记为非桥,同时cnt_bridge--再输出即可。

需要注意的是树边的编号是用树边指向的那个节点的编号来表示的,例如树边<u,v>用编号v表示。

还有就是加入一个#pragma预处理指令可以防止爆栈。

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <cstring>
  4 #include <vector>
  5 using namespace std;
  6 #pragma comment(linker,"/STACk:10240000,10240000")
  7
  8 const int maxn = 100000 + 10;
  9 int low[maxn],pre[maxn], iscut[maxn], dfs_clock=0;
 10 bool isbridge[maxn];
 11 vector<int> G[maxn];
 12 int cnt_bridge;
 13 int father[maxn];
 14
 15 int dfs(int u, int fa)
 16 {
 17     father[u]=fa;
 18     int lowu = pre[u] = ++dfs_clock;
 19     int child = 0;
 20     for(int i = 0; i < G[u].size(); i++)
 21     {
 22         int v = G[u][i];
 23         if(!pre[v])   // 没有访问过v
 24         {
 25             child++;
 26             int lowv = dfs(v, u);
 27             lowu = min(lowu, lowv); // 用后代的low函数更新自己
 28             if(lowv > pre[u]) // 判断边(u,v)是否为桥
 29             {
 30                 isbridge[v]=true;
 31                 cnt_bridge++;
 32             }
 33         }
 34         else if(pre[v] < pre[u] && v != fa)
 35         {
 36             lowu = min(lowu, pre[v]); // 用反向边更新自己
 37         }
 38     }
 39     if(fa < 0 && child == 1)
 40         iscut[u] = 0;
 41     return low[u]=lowu;
 42 }
 43
 44 void init(int n)
 45 {
 46     memset(isbridge,false,sizeof isbridge);
 47     memset(pre,0,sizeof pre);
 48     cnt_bridge=dfs_clock=0;
 49     for(int i=0; i<n; i++)
 50     {
 51         G[i].clear();
 52     }
 53 }
 54
 55 void LCA(int a,int b)
 56 {
 57     while(pre[a]>pre[b])
 58     {
 59         if(isbridge[a])
 60         {
 61             isbridge[a]=false;
 62             cnt_bridge--;
 63         }
 64         a=father[a];
 65     }
 66     while(pre[b]>pre[a])
 67     {
 68         if(isbridge[b])
 69         {
 70             isbridge[b]=false;
 71             cnt_bridge--;
 72         }
 73         b=father[b];
 74     }
 75     if(a!=b)
 76     {
 77         while(pre[a]>pre[b])
 78         {
 79             if(isbridge[a])
 80             {
 81                 isbridge[a]=false;
 82                 cnt_bridge--;
 83             }
 84             a=father[a];
 85         }
 86         while(pre[b]>pre[a])
 87         {
 88             if(isbridge[b])
 89             {
 90                 isbridge[b]=false;
 91                 cnt_bridge--;
 92             }
 93             b=father[b];
 94         }
 95     }
 96 }
 97
 98 int main()
 99 {
100 #ifndef ONLINE_JUDGE
101     freopen("in.txt","r",stdin);
102 #endif
103
104     int n,m,Case=1;
105     while(scanf("%d %d",&n,&m),!(n==0 && m==0))
106     {
107         init(n);
108         for(int i=0; i<m; i++)
109         {
110             int a,b;
111             scanf("%d %d",&a,&b);
112             a--;
113             b--;
114             G[a].push_back(b);
115             G[b].push_back(a);
116         }
117
118         // 第一次dfs找出所有的桥
119         dfs(0,-1);
120         int Q;
121         cin>>Q;
122         printf("Case %d:\n",Case++);
123         while(Q--)
124         {
125             int a,b;
126             scanf("%d %d",&a,&b);
127             a--;
128             b--;
129             LCA(a,b);
130             printf("%d\n",cnt_bridge);
131             if(Q==0)
132                 printf("\n");
133         }
134     }
135
136     return 0;
137 }
时间: 2024-10-24 04:25:31

hdu2460-Network:边的双连通分量的相关文章

POJ1144 Network 题解 点双连通分量(求割点数量)

题目链接:http://poj.org/problem?id=1144 题目大意:给以一个无向图,求割点数量. 这道题目的输入和我们一般见到的不太一样. 它首先输入 \(N\)(\(\lt 100\))表示点的数量(\(N=0\)表示文件输入结束). 然后接下来每行输入一组数字. 如果这一组数字只包含一个 \(0\) ,说明本组测试数据输入结束: 否则,假设这些数可以拆分成 \(a_1,a_2,a_3, \cdots ,a_m\),则说明 \(a_1\) 这个点到 \(a_2,a_3, \cdo

【连通图|边双连通分量+Tarjan+并查集】POJ-3694 Network(400+ms)

Network Time Limit: 5000MS Memory Limit: 65536K Description A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers are connected directly or indirectly by suc

[hdu2460]network(依次连边并询问图中割边数量) tarjan边双联通分量+lca

题意: 给定一个n个点m条边的无向图,q个操作,每个操作给(x,y)连边并询问此时图中的割边有多少条.(连上的边会一直存在) n<=1e5,m<=2*10^5,q<=1e3,多组数据. 题解: 用tarjan求边双连通分量并缩点,缩点后组成一棵树,记录此时割边共有sum条. 连接(x,y),设c[i]为缩点后i所在的新点(边双连通分量),则c[x]-->lca-->c[y]形成一个环,环上的所有边都不再是割边,走一遍并标记,如果遇到没标记过的就sum--. 1 #includ

双连通分量(点-双连通分量&amp;边-双连通分量)

概念: 双连通分量有点双连通分量和边双连通分量两种.若一个无向图中的去掉任意一个节点(一条边)都不会改变此图的连通性,即不存在割点(桥),则称作点(边)双连通图. 一个无向图中的每一个极大点(边)双连通子图称作此无向图的点(边)双连通分量.求双连通分量可用Tarjan算法.--百度百科 Tip:先学一下tarjan算法以及求割点割边的算法之后,再看会比较好理解一些. 点双连通和边双连通 连通的概念:在无向图中,所有点能互相到达 连通分量:互相联通的子图 点双连通:删掉一个点之后,图仍联通 边双连

UVALive - 5135 Mining Your Own Business(双连通分量)

题目大意:有N个矿井 ,由一些隧道连接起来,现在要修建尽量少的安全通道,使得无论哪里发生事故,所有人均能逃出,求建的最少的安全通道数量和方案数 解题思路:建安全通道的话,肯定不能建在割顶,因为割顶如果崩塌了,割顶所连接的双连通分量内的点就跑不掉了,还得在双连通分量里面再建点(上述为双连通分量内部只有一个割顶的情况),这样不划算,还不如直接在里面建点 如果一个双连通分量的内部割顶有多个的话,那么在这个双连通分量里面就可以不用建安全通道了,因为一个割顶崩塌了,还有其他点可以连向外面,所以,只考虑内部

UVALive 5135 Mining Your Own Business 双连通分量 2011final

题意:n条隧道由一些点连接而成,其中每条隧道链接两个连接点.任意两个连接点之间最多只有一条隧道.任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太平井逃脱,求最少安装数量和方案. 思路:其实本题就相当于在一张无向图中,涂尽量少的黑点,使得任意删除哪个点,每个连通分量至少有一个黑点.因为不同的连通分量最多只有一个公共点,那一定是割点.可以发现,涂黑割点是不划算的,而且在 一个点-双连通分量中涂黑两个黑点也是不划算的.所以只有当点-双连通分量只有一个割点时

UVALive-3523 Knights of the Round Table (双连通分量+二分图匹配)

题目大意:有n个骑士要在圆桌上开会,但是相互憎恶的两个骑士不能相邻,现在已知骑士们之间的憎恶关系,问有几个骑士一定不能参加会议.参会骑士至少有3个且有奇数个. 题目分析:在可以相邻的骑士之间连一条无向边,构成一张图G.则问题变成了有几个节点不在奇圈(有奇数个节点的圈)内,并且一个点在圈内最多出现一次.如果G不连通,应该对每一个分量分别求解.奇圈上的点一定在同一个双连通分量内,要找出所有的双连通分量.但是能构成二分图的双连通分量中一定没有奇圈,不能构成二分图的双连通分量中一定含有奇圈,并且分量中所

zoj 2588 Burning Bridges【双连通分量求桥输出桥的编号】

Burning Bridges Time Limit: 5 Seconds      Memory Limit: 32768 KB Ferry Kingdom is a nice little country located on N islands that are connected by M bridges. All bridges are very beautiful and are loved by everyone in the kingdom. Of course, the sys

hihoCoder_#1184_连通性二&#183;边的双连通分量

#1184 : 连通性二·边的双连通分量 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在基本的网络搭建完成后,学校为了方便管理还需要对所有的服务器进行编组,网络所的老师找到了小Hi和小Ho,希望他俩帮忙. 老师告诉小Hi和小Ho:根据现在网络的情况,我们要将服务器进行分组,对于同一个组的服务器,应当满足:当组内任意一个连接断开之后,不会影响组内服务器的连通性.在满足以上条件下,每个组内的服务器数量越多越好. 比如下面这个例子,一共有6个服务器和7条连接: 其中包

POJ 3177 Redundant Paths(边双连通分量)

[题目链接] http://poj.org/problem?id=3177 [题目大意] 给出一张图,问增加几条边,使得整张图构成双连通分量 [题解] 首先我们对图进行双连通分量缩点, 那么问题就转化为给出一棵树,加边使得其成为边双连通分量的最小边数, 只要从叶节点连一条边到任意节点,那么就可以使得这个叶节点加入到双连通分量中, 那么优先叶节点和叶节点连接,所以其答案为(叶节点+1)/2 [代码] #include <cstdio> #include <algorithm> #in