无向连通图的割点、桥

2024-03-20 03:32
文章标签 连通 无向 割点

本文主要是介绍无向连通图的割点、桥,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

无向连通图的割点、桥

泳裤王子原创,转载请注明出处 http://blog.csdn.net/tclh123/article/details/6705392

预备知识

       割点集合

       在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合

       割边集合

在一个无向连通图中,如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合

 

连通度

       点连通度

       一个图的点连通度的定义为,最小割点集合中的顶点数。

       边连通度

       一个图的边连通度的定义为,最小割边集合中的边数。

       双连通图

       如果一个无向连通图的点/边连通度大于1,则称该图是点/边双连通的(biconnected),简称双连通或重连通。 

 

求割点与桥

       概念:

       一个图有割点,当且仅当这个图的点连通度为1,则割点集合唯一元素被称为割点(cut point),又叫关节点(articulation point)。

       一个图有桥,当且仅当这个图的边连通度为1,则割边集合唯一元素被称为(bridge),又叫关节边(articulation edge)。(也有人称为割边….)

       求法:

              使用dfs(深搜)来求割点和桥。先明确一下几点:

1、  图的dfs相当于是对相应的dfs树的遍历。

2、  无向图的dfs树,无论以哪个点为根都可以遍历完所有的点。

3、  无向图的dfs树,没有横叉边(连接两个子树的边)。

(以下结合BYVoid牛神文)

定义dfn[u]为u在dfs搜索树(以下简称为树)中被遍历到的次序号。

定义low[u]为u或u的子树中能通过非父子边追溯到的最早的节点,即dfn[]最小的节点。则有:

low[u]=Min

 {

 dfn[u],

dfn[v] ,// (u,v)为后向边(返祖边) , 等价于 dfn[v]<dfn[u]且v不为u的父亲节点

 low[v], //(u,v)为树枝边(父子边)

 }

所以决定low[u]的关键在于 ,子孙有没有返祖边,返祖边到达的高度是否比dfn[u]小。

//-----------------------------------------------------------------------

①割点u,当且仅当满足(1)或(2)

 (1) u为树根,且u有多于一个子树。

 (2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,即u为v在搜索树中的父亲),使得dfn[u]<=low[v]

 

②桥无向边(u,v),当且仅当(u,v)为树枝边,且满足dfn[u]<low[v]

 

       注:1、为方便程序编写,我们都采用low[v]来判断u。(理论上low[u]也可以判断割点)

 

       例图:

  

       Dfs树:

 

       伪代码:

       Init()

              Dfn[~]= invis[~] = 0;

              RootChild= 0;

       Dfs(u,father)

              Dfn[u]= low[u] = ++index;

              Invis[u]= true;

              Each (u, v)

                     Ifdfn[v]=0            //(u,v)父子边

                            Dfs(v,u)

                            Ifu=Root

                                   RootChild++;

                            Elseif dfn[u]<=low[v]

                                   u is cut

                            Ifdfn[u]<low[v]

                                   (u, v) is brige

                            Low[u] = min(low[u], low[v]);

                     Elseif v!=father && invis[v]=true              //(u,v)返祖边

                            Low[u]= min(low[u], dfn[v]);

                     Invis[u]= false;

              Return;

 

示例代码:

//无向连通图bfs  求	割点、桥
//中间改了几次,写得较烂
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define FF(x1, x2) for(int i=x1; i<x2; i++)
#define MAXN 100
#define MAXM 100
int dfn[MAXN], low[MAXN];		//low
struct edge{int u, v; }a[MAXM];
int first[MAXN], next[MAXM];
int n, m;
int num;
int cut[MAXN], cn;	//割点
edge brige[MAXM];	int bn;//桥
int invis[MAXN];		//正在访问
//也可以统统用颜色标记点,白、灰、黑!!!!!!
int root;
int dfs(int u, int father)		//把 father入栈,避免走反父子边
{
invis[u] = 1;
int child=0;
dfn[u] = low[u] = ++num;		//++num !!!!!!!!!!!!!!!!!!!①
for(int e=first[u]; e!=-1; e=next[e])
{
int v = a[e].v;
if(!dfn[v])	//父子边
{
dfs(v, u);
child++;
if(u!=root && dfn[u]<=low[v]) cut[cn++] = u;					//cut		//要求不是根结点 !!!!!!!!!③
if(dfn[u]<low[v]) brige[bn].u=u, brige[bn++].v=v;		//brige
low[u] = low[u]<low[v]? low[u]: low[v];
}
else if(v != father && invis[v])//反向边		if(v != father) 由于是无向图!确保不要走反父子边
{
low[u] = low[u]<dfn[v]? low[u]: dfn[v];
}
}
invis[u] = 0;
return child;
}
void print()
{
cout<<"cut cn="<<cn<<endl;
FF(0, cn)
{
cout<<i<<"\t"<<cut[i]<<endl;
}
cout<<"brige bn="<<bn<<endl;
FF(0, bn)
{
cout<<i<<"\t"<<"["<<brige[i].u<<","<<brige[i].v<<"]"<<endl;
}
}
void addedge(int u, int v, int e){	next[e] = first[u];	a[e].u = u;	a[e].v = v;	first[u] = e;		}
void read_graph() { memset(first, -1, sizeof(first)); cin>>n>>m; FF(0, m){ int u, v; cin>>u>>v; addedge(u, v, i); addedge(v, u, i+m); } }//无向边
int main()
{
cn = bn = 0;
num=0;		//dfs 的访问 num,用来初始化 dfn
memset(dfn, 0, sizeof(dfn));
memset(invis, 0, sizeof(invis));
read_graph();
/*
//	FF(0, n)
FF(1, n+1)		//	1-index
{
if(!dfn[i])	//未访问
{
if(dfs(i, i)>1) cut[cn++]=i;	// u为树根,且u有多于一个子树。
}
}
*/
//		 无向连通图 bfs 指定任意根一点,必定遍历完。		!!!!!!!!与有向图不一样④
root=1;
if(dfs(1, 1)>1) cut[cn++]=1;	// u为树根,且u有多于一个子树。
print();
}
/*			Demo~
input
6 6
1 2
2 4
4 1
2 3
3 5
5 6
output
cut cn=3
0	5
1	3
2	2
brige bn=3
0	[5,6]
1	[3,5]
2	[2,3]
*/

 


双连通分支

【待续….】




这篇关于无向连通图的割点、桥的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

poj 2914 无向图的最小割

题意: 求无向图的最小割。 解析: 点击打开链接 代码: #pragma comment(linker, "/STACK:1677721600")#include <map>#include <set>#include <cmath>#include <queue>#include <stack>#include <vector>#include <cstd

图的割点、割线问题

图的割点问题 邻接矩阵表示图 package com.hyl.algorithm.other;import java.util.Arrays;import com.hyl.algorithm.search.base.SearchIntf;import com.hyl.algorithm.search.base.SearchIntfFactory;/*** 寻找图的割点* <p>** @aut

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

文章目录 像素的相邻像素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 …