【学习笔记】无向图的连通性

这篇具有很好参考价值的文章主要介绍了【学习笔记】无向图的连通性。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

割点

定义: 在无向图连通图中,若把点 \(x\) 删去后整个图就不连通了,则 \(x\) 为割点(割顶)。

朴素方法: 每次删去一个点,然后判断图是否连通,时间复杂度为 \(O(n(n+m))\)

Tarjan 算法:

\(dfn_x\)\(x\)dfs 到的时间戳

\(low_x\):在 \(x\) 及以后被搜索的所有节点的 \(low\) 值和这些节点能到达的节点的 \(dfn\) 的最小值。

算法流程:

  1. \(1\) 号点开始遍历全图,对于遍历到的点 \(x\),记录它的 \(dfn_x\) 并将 \(low_x\) 的值赋为 \(dfn_x\)
  2. 接下来遍历 \(x\) 的所有子儿子 \(y\)
  • \(y\) 被访问过,则 \(low_x=\min(low_x,dfn_y)\)
  • \(y\) 没有被访问过,则先遍历 \(y\),接着 \(low_x=\min(low_x,low_y)\)

算法原理:

若点 \(x\) 不为割点,把所有没被访问过 \(y\) 放在 \(x\) 的“下方”,则必存在一条边从 \(y\) 连到 \(x\) 的“上方”且这条边在 \(x\) 的“右边”(不然应该先访问到这条边,或者说访问顺序在 \(x\) 之后),按照 \(low\) 数组的定义,则所以的 \(y\) 都满足 \(low_y<dfn_x\)

相反,若 \(x\) 为割点,则必有 \(low_y\ge dfn_x\)(注意,这里有等于号,因为若连到自己则仍为割点)。

特例:\(x\) 为根节点,则肯定存在 \(low_y\ge dfn_x\),判断不出割点,需要特判一下:如果 \(x\) 连接的联通块个数 \(\ge 2\),则其断开后这几个联通块会分开,则 \(x\) 为割点。

void tarjan(int k, int rt) {
	int cnt = 0;
	dfn[k] = low[k] = ++s;
	for (auto i : p[k]) {
		if (!dfn[i]) {
			cnt++;
			tarjan(i, rt);
			low[k] = min(low[k], low[i]);
			if (k != rt && low[i] >= dfn[k]) {
				if (!flag[k]) ans++;
				flag[k] = true;
			 } 
		}
		else low[k] = min(low[k], dfn[i]);
	}
	if (k == rt && cnt > 1) {
		if (!flag[k]) ans++;
		flag[k] = true;
	}
}

时间复杂度:\(O(n+m)\)

割边

定义: 在无向连通图中,若删去某条边,这个图就不连通了,则称这条边是割边(桥)。

Tarjan 算法:

求割边的算法与求割点的算法差不多,只是如果一条从 \(x\)\(y\) 的边为割边,则 \(y\) 不存在边能到 \(y\) 节点及其“上方”,即存在 \(y\) 使 \(low_y>dfn_x\)(这里和割点有所区别)。

代码实现时要注意,这里的边是双向边,为了每条边只访问一次,可以使用邻接链表来存图,这样在边表中一条边 \(e\) 的反向边为 \(e\oplus1\),注意这样存图边的编号得从 \(2\) 开始。

void tarjan(int k) {
	int cnt = 0;
	dfn[k] = low[k] = ++s;
	for (int i = head[k]; i; i = e[i].nxt) {
		if (vis[i]) continue;
		vis[i] = vis[i ^ 1] = true;
		if (!dfn[e[i].to]) {
			tarjan(e[i].to);
			low[k] = min(low[k], low[e[i].to]);
            if (low[e[i].to] > dfn[k])
			    bri[i] = bri[i ^ 1] = true;
		}
		else low[k] = min(low[k], dfn[e[i].to]);
	}
}

时间复杂度:\(O(n+m)\)

点双连通分量(v-Dcc)

定义: 无向图中极大的(不能往外扩张)不存在割点的连通图(割点是指“局部”的割点),其任意两点之间都存在不经过重复点的两条路径。

性质: 一个割点可以存在于多个点双连通分量中,非割点只能存在于一个点双连通分量中,否则其就不是“分量”。

求法: 同样是 Tarjan 算法,不过要开一个栈记录:遍历到 \(x\) 时便把 \(x\) 压入栈,若 \(x\) 为割点,则它通过当前点“吊”着的所有点都弹出(\(x\) 不弹出),而 \(x\) 则是由“吊”着它的点弹出。有个注意点,到 \(y\) 时只应弹出 \(y\) 吊着的这一串,而不是把 \(x\) 吊的所有点都弹出。

特例:\(x\) 为孤立点时,它自成一个点双连通分量。

void tarjan(int k) {
    q.push(k);
	dfn[k] = low[k] = ++s;
	int sum = 0;
	for (auto i : p[k]) {
		if (!dfn[i]) {
			sum++;
			tarjan(i);
			low[k] = min(low[k], low[i]);
			if (low[i] >= dfn[k]) {
				cnt++;
				int t;
				do {
                    t = q.top();
					ans[cnt].push_back(q.top());
					q.pop();
				}while (t != i);
				ans[cnt].push_back(k);
			}
		}
		else low[k] = min(low[k], dfn[i]);
	}
    if (k == rt && sum == 0) ans[++cnt].push_back(k);
}

时间复杂度:\(O(n+m)\)

边双连通分量

定义: 无向图中极大的(不能往外扩张)不存在割边的连通图,其任意两点之间都存在不经过重复边的两条路径。

性质: 割边可以不存在于任何边双连通分量中,非割边只能存在于一个边双连通分量中。

求法: 由于边双连通分量中不包含割边,那么就可以先跑一遍 Tarjan 标记出割边,然后 dfs,不经过割边跑出的联通块就是边双连通分量。

//省略 Tarjan 函数
void dfs(int k)
{
	ans[sum].push_back(k);
	vis[k] = true;
	for (int i = head[k]; i; i = e[i].nxt)
	{
		if (bri[i]) continue;
		int v = e[i].to;
		if (!vis[v]) dfs(v); 
	}
}

练习题

SP2878 KNIGHTS - Knights of the Round Table

洛谷 P3469 [POI2008] BLO-Blockade

洛谷 P2860 [USACO06JAN] Redundant Paths G文章来源地址https://www.toymoban.com/news/detail-611708.html

到了这里,关于【学习笔记】无向图的连通性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 无向图的邻接矩阵

    无向图的邻接矩阵的定义、表示法、度 定义 逻辑结构分为两部分:V和E集合,其中,V是顶点,E是边。因此,用一个一维数组存放图中所有顶点数据;用一个二维数组存放顶点间关系(边或弧)的数据,这个二维数组称为邻接矩阵。邻接矩阵又分为有向图邻接矩阵和无向图邻

    2024年02月04日
    浏览(39)
  • 数据结构|连通图、完全图、无向图、有向图的边数计算问题

    完全图 也称简单完全图。一个图任意两个顶点之间都有边的话,该图就称为完全图。 连通图(一般都是指无向图) 如果图中任意俩顶点都连通,则该图为连通图。 有向图 由点和弧所构成的图( 强连通图必然是有向图,因为强连通和弱连通的概念只在有向图中存在 ) 无向

    2023年04月08日
    浏览(48)
  • 数据结构第12周 :( 有向无环图的拓扑排序 + 拓扑排序和关键路径 + 确定比赛名次 + 割点 )

    【问题描述】 由某个集合上的一个偏序得到该集合上的一个全序,这个操作被称为拓扑排序。偏序和全序的定义分别如下:若集合X上的关系R是自反的、反对称的和传递的,则称R是集合X上的偏序关系。设R是集合X上的偏序,如果对每个x,y∈X必有xRy或yRx,则称R是集合X上的全序

    2024年02月08日
    浏览(42)
  • 图论01-【无权无向】-图的基本表示-邻接矩阵/邻接表

    https://github.com/Chufeng-Jiang/Graph-Theory/tree/main/src/Chapt01_Adjacency 代码有删减 代码有删减 只需要改动一行 adj = new TreeSet[V]; //构造邻接表, V行,V个LinkedList 代码有删减

    2024年02月07日
    浏览(44)
  • 离散数学·通路与回路、图的连通性、连通度

    通路 —— 点边点边……点(点边可以重复) 注意 长度 的概念 ——边数 回路 —— 最后又回到自己,如其字面意思 简单 —— 边互异(边不可重复) 初级 —— 点互异(点不可重复,除了起点终点) 注意 路径 和 圈 所指代的 复杂通路 应该不是很重要,先不看 注意是在 无

    2024年02月03日
    浏览(75)
  • B3610 [图论与代数结构 801] 无向图的块 题解

    2023 2023 2023 ,再见。 2024 2024 2024 ,你好! 其实就是统计点双连通分量的个数。需要注意的是,孤立点在这里不被看作块。本文使用 tarjan 算法来解决这道题。 概念明晰 时间戳:这里记为 d f n i dfn_i df n i ​ ,表示第一次深度优先搜索到节点 i i i 的时间。时间 t i m e ∈ N + t

    2024年02月03日
    浏览(41)
  • 第三章 图论 No.10无向图的双连通分量

    无向图有两种双连通分量 边双连通分量,e-DCC 点双连通分量,v-DCC 桥:删除这条无向边后,图变得不连通,这条边被称为桥 边双连通分量:极大的不含有桥的连通区域,说明无论删除e-DCC中的哪条边,e-DCC依旧连通 (该连通分量的任意边属于原图中的某条环)。此外,任意两

    2024年02月12日
    浏览(40)
  • 数据结构上机实验——图的实现(以无向邻接表为例)、图的深度优先搜索(DFS)、图的广度优先搜索(BFS)

      图采用邻接表存储结构,编程实现图的深度优先搜索和广度优先搜索算法。              2.1创建图 2.1.1定义图的顶点、边及类定义   我们定义一个 邻接表类(ALGraph) 。这里实现一些基础的数据结构。要注意结构体的嵌套。    Edge: 用于表示图中的边

    2024年02月04日
    浏览(54)
  • 带权无向图的邻接矩阵表示法(C语言实现)

    ​ 定义:所谓邻接矩阵存储,是指用一个一维数组存储图中顶点的信息,用一个二维数组存储图中边的信息(即各顶点之间的邻接关系),存储顶点之间邻接关系的二维数组称为邻接矩阵。 ​ 对于 带权图 而言,若顶点V i 和 V j 之间有边相连,则邻接矩阵中对应项存放着该

    2024年02月16日
    浏览(39)
  • 数据结构:有向完全图和无向完全图的边数

    一个拥有n个结点的无向完全图的边数为:n×(n−1)÷2 具体的解释: 比如我们有一个拥有4个结点的无向完全图, 我们首尾依次连接,共有4条边。 然后我们选择其他的两条边来连线。 又多出了2条边。一共有4 + 2 = 6条边。 我们来分析一下具体的过程,首先如果为n个结点的话,

    2024年02月11日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包