嗯,首先边双连通分量(双连通分量之一)是:在一个无向图中,去掉任意的一条边都不会改变此图的连通性,即不存在桥(连通两个边双连通分量的边),称作边双连通分量。一个无向图的每一个极大边双连通子图称作此无向图的双连通分量。

对于边连通分量,我们需要先找出所有的桥,即为所有的桥做上标记。

首先要用dfs的性质来快速找出一个连通图中的所有的桥。

时间戳:表示在进行dfs的时候,每个节点被访问的先后顺序。每个节点会被标记两次,分别用 pre[],和post[]来表示。

在无向图中,只存在两种边,一种是树边(即边和点都没有被访问过),另一种是反向边(即边没有被访问过,但是点已经被访问过)。所以对于根节点而言,如果有两个及以上节点则根节点为割顶,否则不是 
对于其他节点:在无向连通图G的DFS树中,非根节点u是割顶当且仅当u存在一个子节点v,使得v及其所有后代都没有反向边连回u的祖先(不包括u)

然后设low[u]为u及其后代所能连回的最早的祖先的pre[]值,则当u存在节点v使得low[v] >= pre[u]时,u 就为割顶;

而同理当 low[v] > pre[u] 时 u-v 是桥。

接下来直接上求图中割顶和桥的代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <vector>
  5. using namespace std;
  6.  
  7. const int maxn = ;
  8. int n,m; //n为点数,m为边数
  9. int dfs_time; //时间戳
  10. vector<int>G[maxn];
  11. int low[maxn],pre[maxn];
  12. int iscut[maxn];//会标记是否为割顶
  13.  
  14. int dfs(int u,int fa){
  15. int lowu = pre[u] = ++dfs_time;
  16. int child = ;
  17. for(int i = ;i < G[u].size();i++){
  18. int v = G[u][i]; //v是u所连接的点
  19. if(!pre[v]) //没有访问过
  20. {
  21. child++; //孩子的节点数
  22. int lowv = dfs(v,u);
  23. lowu = min(lowu,lowv); //用后代更新lowu
  24.  
  25. //是割顶的判断条件
  26. if(lowv >= pre[u])
  27. iscut[u] = ;
  28.  
  29. //是桥的判断条件
  30. if(lowv > pre[u])
  31. printf("%d -- %d 是桥\n",u,v);
  32. }
  33. else if(pre[v] < pre[u] && v != fa){
  34. //是反向边的情况,就更新lowu
  35. lowu = min(lowu,pre[v]);
  36. }
  37. return lowu; //返回当前节点及其子节点能回到的最早祖先的pre值
  38. }
  39. }
  40.  
  41. int main(){
  42. while(scanf("%d%d",&n,&m)!=EOF){
  43. memset(pre,,sizeof(pre));
  44. memset(iscut,,sizeof(iscut));
  45. for(int i = ;i <= n;i++)
  46. G[i].clear();
  47. int u,v; //u -> v
  48. for(int i = ;i < m;i++){
  49. scanf("%d%d",&u,&v);
  50. G[u].push_back(v); //在u中添加v
  51. G[v].push_back(u); //在v中添加u(因为是无向图)
  52. }
  53. dfs(,-); //u是当前节点,fa是父节点
  54. printf("割顶有:");
  55. for(int i = ;i <= n;i++){
  56. if(iscut[i]) //如果是割顶
  57. printf("%d ",i);
  58. }
  59. }
  60. return ;
  61. }

第一步已经完成(对桥做标记)。然后利用dfs遍历连通分量,只不过在遍历的时候不能访问桥。

上代码:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <vector>
  5. using namespace std;
  6.  
  7. const int maxn = ;
  8. struct Edge
  9. {
  10. int no,v,next; //no:边的编号
  11. }edges[maxn];
  12.  
  13. int n,m,ebcnum; //节点数目,无向边的数目,边_双连通分量的数目
  14. int e,head[maxn];
  15. int pre[maxn]; //第一次访问的时间戳
  16. int dfs_clock; //时间戳
  17. int isbridge[maxn]; //标记边是否为桥
  18. vector<int> ebc[maxn]; //边_双连通分量
  19.  
  20. void addedges(int num,int u,int v) //加边
  21. {
  22. edges[e].no = num;
  23. edges[e].v = v;
  24. edges[e].next = head[u];
  25. head[u] = e++;
  26. edges[e].no = num++;
  27. edges[e].v = u;
  28. edges[e].next = head[v];
  29. head[v] = e++;
  30. }
  31.  
  32. int dfs_findbridge(int u,int fa) //找出所有的桥
  33. {
  34. int lowu = pre[u] = ++dfs_clock;
  35. for(int i=head[u];i!=-;i=edges[i].next)
  36. {
  37. int v = edges[i].v;
  38. if(!pre[v])
  39. {
  40. int lowv = dfs_findbridge(v,u);
  41. lowu = min(lowu,lowv);
  42. if(lowv > pre[u])
  43. {
  44. isbridge[edges[i].no] = ; //桥
  45. }
  46. }
  47. else if(pre[v] < pre[u] && v != fa)
  48. {
  49. lowu = min(lowu,pre[v]);
  50. }
  51. }
  52. return lowu;
  53. }
  54.  
  55. void dfs_coutbridge(int u,int fa) //保存边_双连通分量的信息
  56. {
  57. ebc[ebcnum].push_back(u);
  58. pre[u] = ++dfs_clock;
  59. for(int i=head[u];i!=-;i=edges[i].next)
  60. {
  61. int v = edges[i].v;
  62. if(!isbridge[edges[i].no] && !pre[v]) dfs_coutbridge(v,u);
  63. }
  64. }
  65.  
  66. void init()
  67. {
  68. memset(pre,,sizeof(pre));
  69. memset(isbridge,,sizeof(isbridge));
  70. memset(head,-,sizeof(head));
  71. e = ;
  72. ebcnum = ;
  73. }
  74.  
  75. int main()
  76. {
  77. int u,v;
  78. while(scanf("%d%d",&n,&m)!=EOF)
  79. {
  80. init();
  81. for(int i=;i<m;i++)
  82. {
  83. scanf("%d%d",&u,&v);
  84. addedges(i,u,v);
  85. }
  86. dfs_findbridge(,-); //进行找桥
  87. memset(pre,,sizeof(pre));
  88. for(int i=;i<=n;i++)
  89. {
  90. if(!pre[i])
  91. {
  92. ebc[ebcnum].clear();
  93. dfs_coutbridge(i,-);
  94. ebcnum++;
  95. }
  96. }
  97. for(int i=;i<ebcnum;i++)
  98. {
  99. for(int j=;j<ebc[i].size();j++)
  100. printf("%d ",ebc[i][j]);
  101. printf("\n");
  102. }
  103. }
  104. return ;
  105. }

无向图的边双连通分量(EBC)的更多相关文章

  1. 无向图的点双连通分量(tarjan模板)

    #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #i ...

  2. Bridges Gym - 100712H  无向图的边双连通分量,Tarjan缩点

    http://codeforces.com/gym/100712/attachments 题意是给定一个无向图,要求添加一条边,使得最后剩下的桥的数量最小. 注意到在环中加边是无意义的. 那么先把环都 ...

  3. Graph_Master(连通分量_A_双连通分量+桥)

    hdu 5409 题目大意:给出一张简单图,求对应输入的m条边,第i-th条边被删除后,哪两个点不连通(u,v,u<v),若有多解,使得u尽量大的同时v尽量小. 解题过程:拿到题面的第一反应缩点 ...

  4. HDU 4612——Warm up——————【边双连通分量、树的直径】

    Warm up Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Stat ...

  5. Redundant Paths 分离的路径【边双连通分量】

    Redundant Paths 分离的路径 题目描述 In order to get from one of the F (1 <= F <= 5,000) grazing fields ...

  6. POJ 3352 无向图边双连通分量,缩点,无重边

    为什么写这道题还是因为昨天多校的第二题,是道图论,HDU 4612. 当时拿到题目的时候就知道是道模版题,但是苦于图论太弱.模版都太水,居然找不到. 虽然比赛的时候最后水过了,但是那个模版看的还是一知 ...

  7. Expm 9_3 无向图的双连通分量问题

      [问题描述] 给定一个无向图,设计一个算法,判断该图中是否存在关节点,并划分双连通分量. package org.xiu68.exp.exp9; import java.util.Stack; p ...

  8. DFS的运用(二分图判定、无向图的割顶和桥,双连通分量,有向图的强连通分量)

    一.dfs框架: vector<int>G[maxn]; //存图 int vis[maxn]; //节点访问标记 void dfs(int u) { vis[u] = ; PREVISI ...

  9. tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)

    基本概念 给定无向连通图G = (V, E)割点:对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点割边(桥)若对于e∈E,从图中删去边e之后,G分 ...

随机推荐

  1. libusb 源码阅读

    libusb_init(NULL), 如果传入一个NULL, 则libusb 内部会有一个 usbi_default_context 变量在内部保存上下文. 这样以后调用 libusb 函数时可以不指 ...

  2. ln: 正在创建指向“asm-arm”的符号链接“asm”: 不支持的操作

    原因是不能在windows共享目录编译,将待编译的uboot源码copy到home目录

  3. appium 查错

    很高兴最近论坛用appium的人多了不少,但也有不少由于不了解appium导致出现错误后不知道从何下手.这里根据我的个人经验给出一个简单的查错指南,不保证能解决所有错误,但至少让你知道你应该朝哪个方向 ...

  4. win7 64位安装vs2013 出现'System.AccessViolationException的错误

    用管理员身份运行CMD,输入netsh winsock reset并回车(注意,必须是已管理员身份运行,这个重置LSP连接)

  5. MySQL 数据库 的安装和基本管理

    03-MySql安装和基本管理   本节掌握内容: mysql的安装.启动 mysql破解密码 统一字符编码 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Orac ...

  6. HBase数据压缩编码探索

    摘要: 本文主要介绍了hbase对数据压缩,编码的支持,以及云hbase在社区基础上对数据压缩率和访问速度上了进行的改进. 前言 你可曾遇到这种需求,只有几百qps的冷数据缓存,却因为存储水位要浪费几 ...

  7. Bootstrap progress-bar

    1.进度条 在网页中,进度条的效果并不少见,比如一个评分系统,比如加载状态等.就如下图所示的一个评分系统,他就是一个简单的进度条效果: 进度条和其他独立组件一样,开发者可以根据自己的需要,选择对应的版 ...

  8. 图像物体检測识别中的LBP特征

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/xinzhangyanxiang/article/details/37317863 图像物体检測识别中 ...

  9. 学习js所必须要知道的一些

    1.document.write(""); 输出语句 2.JS中的注释为// 3.传统的HTML文档顺序是:document->html->(head,body) 4. ...

  10. html5--6-28 css盒模型4

    html5--6-28 css盒模型4 实例 学习要点 了解盒模型 元素内容.内边距.边框 和 外边距 了解盒模型的概念: CSS 盒模型规定了处理元素内容.内边距.边框 和 外边距 的方式. 最内部 ...