文章目录

  • 点双连通分量
    • 前言
    • 概念
    • 性质
    • 找割点
    • 找点双
    • 附赠题表
  • 边双连通分量
      • 概念
      • 性质
      • 找割边
      • 找边双
        • 做法1
        • 做法2
      • 题表
    • 一点个人感想

点双连通分量

前言

由于点双和边双都是无向图里面的东西,所以下面的讲解都以图是无向图作为前提。

概念

割点: 对于一个连通图中的点 xxx,假如删去这个点以及与所有 xxx 相连的边之后图不连通,那么称 xxx 为该图的割点

点双联通的: 对于一个无向图,假如仅仅对于该图而言其中不包含割点,那么称这个图是点双连通的。(和网上的不一样?别急,往下看)

点双连通分量: 对于一个无向图中的极大点双连通的子图,我们称这个子图为点双连通分量

为了方便,下面简称点双连通分量为点双。

性质

1、 除了一种比较特殊的点双,其他的点双都满足:任意两点间都存在至少两条点不重复路径。

比较特殊的点双:

网上大部分以该性质作为点双的定义,然后说这种图虽然不满足定义,但是是一个特殊的点双。而上面那个更严谨的定义则可以将这种情况包含在内,更加完备。

2、 图中任意一个割点都在至少两个点双中。

因为删去割点后图会不连通,所以割点至少连接着图的两部分,而由于点双中不能有割点,所以这两部分肯定不在同一个点双中,所以割点至少存在于两个点双中。

再次提醒,点双联通的的定义是 仅仅对于该图而言 其中不包含割点,那么称这个图是点双连通的,也就是说,可以包含原图中的割点。

3、 任意一个不是割点的点都只存在于一个点双中。

这个很显然,不多解释。

找割点

设 dfn[x]dfn[x]dfn[x] 表示遍历到 xxx 之前遍历过多少个点,low[x]low[x]low[x] 表示从 xxx 出发在不经过父子边的情况下能到达的最早的祖先的 dfndfndfn 值。

回看割点的定义:把这个点删除后图会不连通,那么肯定存在一些点,在不经过该割点的情况下无法到达割点的祖先,用这个性质来找就好了。

代码:

int dfn[maxn],low[maxn],id;
bool cut[maxn];
void dfs1(int x,int from)//from表示x与父亲之间的边的编号
{dfn[x]=low[x]=++id; int son=0;for(int i=first[x];i;i=e[i].next){int y=e[i].y;if(y==(from^1))continue;//不能通过反向边走回去if(!dfn[y]){dfs1(y,x); son++;if(low[y]<low[x])low[x]=low[y];//更新low,假如y能走到更小的,那么x也能走到if(low[y]>=dfn[x])cut[x]=true;//假如儿子在不经过父子边的情况下不能到达x的祖先,那么x就是个点}else if(dfn[y]<low[x])low[x]=dfn[y];//假如走到了一个dfn更小的,那么更新low}if(fa==-1&&son==1)cut[x]=false;//特判出发点在一个环中的情况
}
void tarjan()
{for(int i=1;i<=n;i++)//如果图不连通,那么每一个连通块都要跑一遍if(dfn[i]==0)dfs1(i,-1);
}

再说说那个特判,是用来处理这种情况的:

假如从红色节点出发,那么最后红色节点会被判定成割点,因为没有儿子能走到它的祖先,但是他压根就没有祖先啊,所以这时候,我们判一下,假如没有祖先,那么不能算割点,于是有了

fa==-1

这个判定条件。

但是

son==1

这个条件用来干啥?

我们注意到,出发点也有是割点的情况,比如:

如果从红色节点出发,而此时红色节点又刚好是割点,那怎么办呢?

这时候就要用到

son==1

这个限制了,因为如果起点是割点,那么 sonsonson 肯定大于 111。

发现只有遍历到一个 dfn[y]=0dfn[y]=0dfn[y]=0 的 yyy 时,sonsonson 才会 +1+1+1,所以 sonsonson 的实际意义就是该点所连接的点双数量。

而根据上面的性质,假如 son==1son==1son==1,那么这个点肯定不是割点,否则一定是割点,所以在 fa=−1fa=-1fa=−1 的同时我们还需要进行 son=1son=1son=1 这样的判断。

那可能有人会问了,为什么其他的割点不用 son=1son=1son=1 这样的方法来判呢?仔细想想,其他的点和出发点的区别就是:他们都有父亲。而遍历的时候是不能往回走的,也就是说,我们不知道父亲的状态,所以不能用 sonsonson 来判。

找点双

这个时候就要请出伟大的 Tarjan 了!

我们依然考虑使用上面的 dfndfndfn 和 lowlowlow 来求,我们将深搜时遇到的所有加入到栈里面,当找到一个割点的时候,就将这个割点往下走到的所有边弹出,而这些边所连接的点就是一个点双了。

代码:

int dfn[maxn],low[maxn],id,t;
edge zhan[(maxn*maxn)<<1];//存边的栈
int belong[maxn],cnt;//belong记录每个点属于哪一个点双,cnt记录点双个数
bool cut[maxn];
set<int> s[maxn];//记录每个点双包含哪些点,如果题目不需要也可以不求
void dfs(int x,int from)
{dfn[x]=low[x]=++id; int son=0;for(int i=first[x];i;i=e[i].next){if(i==(from^1))continue;int y=e[i].y;if(!dfn[y]){zhan[++t]=e[i]; dfs(y,i); son++;//先压栈再遍历if(low[y]<low[x])low[x]=low[y];if(low[y]>=dfn[x])//发现x是割点{cnt++; edge xx; cut[x]=true;do{xx=zhan[t--];//弹出belong[xx.x]=belong[xx.y]=cnt;//标记s[cnt].insert(xx.x);s[cnt].insert(xx.y);//记录}while(xx.x!=x||xx.y!=y);//假如已经弹到 x到y 这条边了,就停下来}}else if(dfn[y]<low[x])low[x]=dfn[y];}if(from==-1&&son==1)cut[x]=false;
}

附赠题表

Knights of the Round Table   题解
[HNOI2012]矿场搭建   题解
[ZJOI2004]嗅探器   题解


边双连通分量

概念

割边: 假如删去这条边后图不连通,那么称这条边为割边。

边双联通的: 对于一个图,假如仅仅对于该图而言其中没有割边,那么我们称这个图是边双联通的

性质

1、 割边不属于任意边双,而其它非割边的边都属于且仅属于一个边双。

2、 对于一个边双中的任意两个点,它们之间都有至少两条边不重复的路径。

找割边

和找割点类似,直接上代码:

int dfn[maxn],low[maxn],id;
bool cut[maxn];
void dfs(int x,int from)
{dfn[x]=low[x]=++id;for(int i=first[x];i;i=e[i].next){if(i==(from^1))continue;int y=e[i].y;if(!dfn[y]){dfs(y,i);if(low[y]<low[x])low[x]=low[y];if(low[y]>dfn[x])cut[i]=cut[i^1]=true;//注意这里是大于而不是大于等于,原因想想就明白了}else if(dfn[y]<low[x])low[x]=dfn[y];}
}

找边双

做法1

在请出Tarjan之前,我们先介绍另外一种做法:第一次 dfsdfsdfs 找出割边,然后第二次 dfsdfsdfs 在不经过割边的情况下遍历所有点,每一次遍历经过的一个子图就是一个边双。

做法2

用类似找点双的做法,但是栈里面压点,不压边。

代码:

int dfn[maxn],low[maxn],belong[maxn],id=0,cnt=0;
int zhan[maxn],t=0;
void dfs(int x,int from)
{dfn[x]=low[x]=++id;zhan[++t]=x;for(int i=first[x];i;i=e[i].next){if(i==(from^1))continue;int y=e[i].y;if(!dfn[y]){dfs(y,i);if(low[y]<low[x])low[x]=low[y];}else if(dfn[y]<low[x])low[x]=dfn[y];}if(dfn[x]==low[x]){cnt++; int xx;do{xx=zhan[t--];belong[xx]=cnt;}while(xx!=x);}
}

题表

Caocao’s Bridges   题解
[CERC2015]Juice Junctions   题解
[USACO06JAN]冗余路径Redundant Paths   题解

一点个人感想

对于什么时候用点双,什么时候用边双这个问题,个人感觉是,点双的性质其实比边双要好,因为边双里面允许有割点的存在,边双只强调点集内所有点能相互到达,但点双就有一些更好的性质,比如像吃掉一个点之后剩下的点之间还能相互到达。

当然这些都是乱吹的,建议不看跳过即可。

点双连通分量边双联通分量详解相关推荐

  1. 强联通分量,双联通分量详解

    正题 强联通分量 我们开两个数组 l o w , d f n low,dfn low,dfn . d f n dfn dfn 表示 i i i 点的 d f s dfs dfs 序, l o w lo ...

  2. 双连通分量(点-双连通分量边-双连通分量)

    概念: 双连通分量有点双连通分量和边双连通分量两种.若一个无向图中的去掉任意一个节点(一条边)都不会改变此图的连通性,即不存在割点(桥),则称作点(边)双连通图. 一个无向图中的每一个极大点(边)双连 ...

  3. python创建双链表_Python双链表原理与实现方法详解

    本文实例讲述了Python双链表原理与实现方法.分享给大家供大家参考,具体如下: Python实现双链表 文章目录 Python实现双链表 单链表与双链表比较 双链表的实现 定义链表节点 初始化双链表 ...

  4. 双冒号作用运算符以及命名空间详解

    转载地址:双冒号作用运算符以及命名空间详解,你确定不来看看吗?_敲键盘的喵的博客-CSDN博客 一.双冒号作用域运算符 通常情况下,如果程序中即存在局部变量又存在全局变量,局部变量将会获得较高的优先权 ...

  5. 强连通分量/点双连通分量/边双联通分量 总结

    前言 % 被某brz逼着问,觉得很有必要好好复习一下这 些 毒瘤东西. 定义 % 连通 如果有向图中的两点 uuu,vvv 间同时存在 uuu 到 vvv 的路径及 vvv 到 uuu 的路径,则称点 ...

  6. 图论--双连通分量--点双连通模板

    #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #incl ...

  7. dreamweaver 正则表达式为属性值加上双引号_PHP正则表达式核心技术完全详解 第2节...

    PHP 正则表达式核心技术完全详解 第2节 接上一节内容 1 普通字符作为原子 /5/ 用于匹配字符串中是否有5这个字符出现 /php/ 用于匹配字符串中是否有PHP字符串出现 /  / 匹配空字符串 ...

  8. 深度学习目标检测2013-2018单双阶段主流模型概览及详解

    背景:深度学习引入目标检测领域以来,给目标检测领域带来了很多突破性的进展,文章"Deep Learning for Generic Object Detection: A Survey&qu ...

  9. 2019双11猫晚直播技术详解(附演讲PDF)

    下载演讲PDF版 链接可能被微信屏蔽, 请使用钉钉/支付宝扫码,或复制到浏览器中 本文为阿里文娱技术专家泫野在[阿里文娱2019双11猫晚技术沙龙]中的演讲,主要内容为双11猫晚直播的技术挑战.破解策 ...

最新文章

  1. Android10.0 Binder通信原理(七)-Framework binder示例
  2. 用神经网络解释化学键能 化学键的键能:一个方程组的特征解
  3. 欢乐纪中某A组赛【2019.7.9】
  4. 持续定义Saas模式云数据仓库+BI
  5. realloc函_realloc(重新分配内存空间的函数)
  6. mysql 语句 not_mysql sql语句 is not 用法是
  7. [再学Python] - 3 - 异常处理 try…except…
  8. 熊猫可用人脸识别?大熊猫迎来熊生高光时刻,以后终于可以认清我了
  9. 收藏!豆瓣9.0分TOP100职场终极必读书单!大萌哥整理
  10. 国内各类有用搜索网站汇总
  11. 英语听力采用计算机化考试,高考英语复习资料及听力机考特点与应对建议
  12. 《ECMAScript 6 入门教程》学习笔记Ⅰ
  13. Halcon算子说明
  14. [重点]C语言——数组
  15. 嵌入式毕设分享 stm32人体健康状态检测系统(项目开源)
  16. uniapp登录授权获取微信手机号组件封装
  17. 商用车SCR系统行业调研报告 - 市场现状分析与发展前景预测
  18. 浙大MBA考研经验分享:名校梦不可负~
  19. 2021年苍南桥墩高中高考成绩查询,2021年温州各高中高考成绩排名及放榜最新消息...
  20. PowerBI把日期戳格式转换成常见日期格式

热门文章

  1. s7填表指令att_这些PLC指令你会用吗?plc编程入门
  2. L1-038 新世界 Python
  3. 【Linux】冯诺依曼体系结构
  4. php nss,GSM 网络交换子系统(NSS)
  5. pymysql dataframe,DataFrame constructor not properly called
  6. Java中Type接口与Class类的区别联系
  7. 大众点评搜索相关性技术探索与实践
  8. 2021 年最新的个人录制的前后端真正的免费编程学习视频
  9. 禁止 mysql nobody_linux中nobody账号的相关解释
  10. 2022-2028全球与中国实验室烧结炉市场现状及未来发展趋势