Tarjan-vDCC,点双连通分量,点双连通分量缩点

2023-12-22 22:28

本文主要是介绍Tarjan-vDCC,点双连通分量,点双连通分量缩点,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

双连通分量是无向图中的一个概念,它是指无向图中的一个极大子图,根据限制条件可以分为边双连通分量和点双连通分量,欲了解双连通分量需先了解Tarjan算法,以及割点割边的概念及求解。本篇博客介绍点双连通分量的相关内容。


前置知识

学习点双连通分量前,你需要先了解:

关于Tarjan:SCC-Tarjan算法,强连通分量算法,从dfs到Tarjan详解-CSDN博客
关于缩点:SCC-Tarjan,缩点问题-CSDN博客
关于割点:Tarjan-割点问题-CSDN博客
关于割边:Tarjan-割边问题-CSDN博客


点双连通分量的定义

在无向图中,存在一个极大子图,其中任意两个顶点之间连通,并且删除任意一点该子图仍然是连通的,我们称该极大子图为点双连通分量(vertex Double Connected Components,vDCC)

推论

  • 无向图中极大的不包含割点的连通分量被称为点双连通分量(vertex Double Connected Components,vDCC)

  • 一个割点存在于至少两个双连通分量之中

如下图中1、5为割点,{1,2,3,4}, {1,5},{5,6}, {5,7,8}均为vDcc

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=C%3A%5CUsers%5C在这里插入图片描述
%E5%8F%B2%E9%91%AB%E9%98%B3%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20231222195235335.png&pos_id=img-r6Pf4tFh-1703247458562)

Tarjan算法求解vDcc

我们回顾一下Tarjan算法涉及到的概念:

搜索树

我们dfs对图遍历,保证每个点只访问一次,访问过的节点和边构成一棵有向树,我们称之为搜索树

强连通分量的根

如果节点x是某个强连通分量在搜索树中遇到的第一个节点,那么这个强连通分量的其余节点肯定是在搜索树中以x为根的子树中。节点x被称为这个强连通分量的根

时间戳

我们用数组dfn[]来保存节点第一次访问时间,dfn[x]即节点x第一次访问的时间戳

追溯值

数组low[]来记录每个节点出发能够访问的最早时间戳,记low[x]节点x出发能够访问的最早时间戳,即追溯值


算法原理

仍然是基于Tarjan算法进行求解,其实就是Tarjan算法求解割点和强连通分量的结合。

我们Tarjan在有向图求SCC中,通过栈保存连通分量的节点,又通过时间戳和追溯值是否相等来找到强连通分量的根从而从栈中取出节点
而求解割点时,我们对于low值更新是不允许越过父节点来更新low值的,即我们else代码段中的low[x] = min(low[x], dfn[y]);

那么我们如何来记录点双连通分量呢?

点双连通分量的记录

和求解SCC,eDCC一样,借助栈来保存节点以及取出连通分量中的点。不过与前两者不同的是,前者在完成子节点遍历后根据时间戳和追溯值判断根来取出连通分量中的节点,而vDCC要在出现一个子节点y满足low[y] >= dfn[x]时就进行vDCC的记录。为什么呢?

如下图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1为割点,但是点双连通分量为{1,4,5}和{1,2,3},也就是说对于一个割点它可以是多个环的环顶,所以遍历完一个环就要把这个环和割点本身记录为一个点双连通分量。

孤立点和自环的特判

孤立点

我们的图中如果有孤立点的话,其自身就是一个vDCC,所以对于孤立点我们直接给他开个单间,放到一个vDCC中,不过出不出栈无所谓,因为孤立点不影响前面的vDCC和后面的vDCC。

自环

如果是含有多个点的vDCC的话我们不用特殊处理,自然会归到相应的vDCC,但如果是孤立自环也就是说孤立点的自环的话,我们需要特判,很简单,我们tarjan求割点要记录child,对于孤立点自环child自然为0而且low[x] == dfn[x],以此特判即可,后面代码会具体实现。


算法流程
  • 给x打时间戳,入栈
  • 如果是孤立点,直接开单间,返回
  • 否则遍历子节点y,记录child,
  • low[y] >= dfn[x],child++,根据情况记录割点,然后记录vDCC
  • 离开函数时特判孤立点自环
代码实现

仍然是使用链式前向星存图,关于链式前向星,详见:一种实用的边的存储结构–链式前向星-CSDN博客

#define N 500010
#define M 4000010
struct edge
{int v, nxt;
} edges[M];
int head[N], idx = 0;
void addedge(int u, int v)
{edges[idx] = {v, head[u]};head[u] = idx++;
}
int n, m, dfn[N], low[N], st[N], tot = 0, cnt = 0, top = 0, root;
bitset<N> cut;
vector<int> vdcc[N];
void tarjan(int x)
{low[x] = dfn[x] = ++tot;st[top++] = x;// 孤立点if (head[x] == -1){vdcc[++cnt].emplace_back(x);return;}int child = 0, y;for (int j = head[x]; ~j; j = edges[j].nxt){y = edges[j].v;if (!dfn[y]){tarjan(y);low[x] = min(low[x], low[y]);if (low[y] >= dfn[x]){child++;if (x != root || child > 1)cut[x] = 1;cnt++;int z;do{z = st[--top];vdcc[cnt].emplace_back(z);} while (z != y);vdcc[cnt].emplace_back(x);}}elselow[x] = min(low[x], dfn[y]);}// 孤立点自环if (!child && dfn[x] == low[x])vdcc[++cnt].emplace_back(x);
}

vDcc缩点问题

vDCC缩点相较于SCC缩点和eDCC缩点也有所不同,因为涉及到了割点的分裂,所以每个vDCC缩点后是跟割点进行相连,vDCC缩点后也会得到一棵树或森林。

代码实现如下:g为缩点图的邻接表存储

//vector<int> vdcc[N], g[N];int num = cnt;
for (int i = 1; i <= n; i++)if (cut[i])id[i] = ++num;
for (int i = 1; i <= cnt; i++)for (auto x : vdcc[i]){if (cut[x]){g[i].emplace_back(id[x]);g[id[x]].emplace_back(i);}}

OJ练习

P8435 【模板】点双连通分量 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这篇关于Tarjan-vDCC,点双连通分量,点双连通分量缩点的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/525678

相关文章

线性因子模型 - 独立分量分析(ICA)篇

序言 线性因子模型是数据分析与机器学习中的一类重要模型,它们通过引入潜变量( latent variables \text{latent variables} latent variables)来更好地表征数据。其中,独立分量分析( ICA \text{ICA} ICA)作为线性因子模型的一种,以其独特的视角和广泛的应用领域而备受关注。 ICA \text{ICA} ICA旨在将观察到的复杂信号

像素间的关系(邻接、连通、区域、边界、距离定义)

文章目录 像素的相邻像素4邻域D邻域8邻域 邻接、连通、区域和边界邻接类型连通区域边界 距离测度欧氏距离城市街区距离(city-block distance)棋盘距离(chessboard distance) 参考 像素的相邻像素 4邻域 坐标 ( x , y ) (x,y) (x,y)处的像素 p p p有2个水平的相邻像素和2个垂直的相邻像素,它们的坐标是: ( x

OpenCV结构分析与形状描述符(6)带统计的连通组件计算函数connectedComponentsWithStats()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 connectedComponentsWithStats 函数计算布尔图像的连通组件标记图像,并为每个标记产生统计信息。 该函数接受一个具有4或8连通性的二值图像,并返回 N,即标签总数(标签范围为 [0, N-1],其中 0 代表背景标签)

最小连通网络

使用网络中的n-1条边来连接网络中的n个顶点 不产生回路 各边上的权值总和达到最小 prim算法:针对顶点展开,适合边的数量较多的情况 kruskal算法:针对边展开的,适合边的数量较少的情况

【HDU】2242 考研路茫茫——空调教室 双连通分量+树型DP

考研路茫茫——空调教室 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1978    Accepted Submission(s): 576 Problem Description 众所周知,HDU的考研教室是没

【HDU】3861 The King’s Problem 强连通缩点+有向图最小路径覆盖

传送门:【HDU】3861 The King’s Problem 题目分析:首先强连通缩点,因为形成一个环的王国肯定在一条路径中,这样才能保证拆的少。 然后缩点后就是DAG图了,由于题目要求的是最小路径覆盖,那么二分匹配即可。 代码如下: #include <cstdio>#include <cstring>#include <algorithm>#includ

【Live Archive】6393 Self-Assembly【强连通】

传送门:【Live Archive】6393 Self-Assembly 题目分析: 假设我们只用到向上或者向右的块,这样我们只要找到一个回路使得某个块可以和第一个块一样,那么我们就相当于找到了一个循环,这样就可以无限循环了。 但是我们要怎样去找这么一个环?考虑到必须是对应字母 X+,X− X^+,X^-才能建边,然后一个环中一定是多个一对一对的这样的对应字母组成的。 可以发现块的数量那么

OpenCV_连通区域分析(Connected Component Analysis-Labeling)

申明:本文非笔者原创,原文转载自:http://blog.csdn.net/icvpr/article/details/10259577 OpenCV_连通区域分析(Connected Component Analysis/Labeling) 【摘要】 本文主要介绍在CVPR和图像处理领域中较为常用的一种图像区域(Blob)提取的方法——连通性分析法(连通区域标

强连通分量专题总结

~~~~~      总题单链接 ~~~~~      对于只需要考虑强连通分量的题,就可以用强连通分量(大雾 ~~~~~      我想了很久,确实没有什么好说的 … \ldots …

缩点专题总结

~~~~~      总题单链接 ~~~~~      缩点,就是把一个强连通分量缩成一个点。 ~~~~~      若我们不需要每个点的信息,只需要每个强连通分量的信息就可以用缩点。 ~~~~~      缩点后的图是一颗树或者森林,有着非常好的性质。