割点和桥

快乐地打牢基础(5)——割点和桥 一、定义 点连通度: 边连通度: 阅读详情

先介绍一些基础定义:(都是针对无向图)
点连通度与边连通度
在一个无向连通图中,如果有一个顶点集合V,删除顶点集合V以及与V中顶点相连(至少有一端在V中)的所有边后,原图不连通,就称这个点集V为割点集合。
一个图的点连通度:最小割点集合中的顶点数。
如果一个边集合,删除这个边集合后,原图不连通,就称这个边集为割边集合。
一个图的边连通度:最小割边集合中的边数。

点双连通:如果一个无向连通图的点连通度大于1,则称该图是点双连通的,简称双连通或者重连通(即删去任意一点原图任然连通)。
割点:一个图有割点,当且仅当这个图的点连通度为1时,割点集合的唯一元素被称为割点(即删去割点原图不连通),一个图可能有多个割点。
PS:有割点的图不一定有割边。

边双连通:如果一个无向连通图的边连通度大于1,则称该图是边双连通的,简称双连通或者重连通(即删去任意一边原图任然连通)。
桥:一个图有桥,当且仅当这个图的边连通度为1时,割边集合的唯一元素被称为桥(即删去桥原图不连通),一个图可能有多个桥。
PS:有割边的图不一定有割点。

双连通分量:在图G的所有子图G’中,如果G’是双连通的,则称G’是双连通子图。如果一个双连通子图G’,他不是任何一个双连通子图的真子集,则称G’为极大双连通子图,双连通分量或重连通分量。特殊的是点双连通分量又叫做块。
PS:边双连通分量一定是点双连通分量,但点双连通分量不一定是边双连通分量。

在求双连通分量的注意点:
割点可以属于多个点双连通分量,其余点和边只属于一个点双连通分量。

将一个有桥图通过加边变成边双连通分量时:
如果叶子数(缩点后度为1的点)为1,则至少需要添加0条边;
否则为(叶子数+1)/ 2;

判断割点:
一个顶点u是割点,当且仅当满足下列两个条件之一:
1:u为树根,且u有多余一个子树。因为如果只有一颗子树,去掉根节点后肯定不会出现多颗子树,因此不可能为割点;而无向图dfs搜索树中不存在横叉边,所以若有多个子树,这些子树间不会有边相连,因此u肯定是割点。
2:u不为树根,且满足存在(u,v)为树枝边(即u为v在搜索树中的父亲),并使得dfn[u] <= low[v]。(因为删去u后v的子树不能到达u的祖先)。

判断桥
一条无向边(u,v)是桥,当且仅当(u,v)为树枝边且满足dfn[u] < low[v]。(因为v想要到达u的父亲必须经过(u,v)这条边,所以删去这条边,图不连通)。
PS:在判断(u,v)是否有后向边时要注意判断是树枝边的反向边还是新的一条边。


桥模板
求桥://cnt 都从 1 开始

int pre[N],vis[M],sum,bridge[M];
void tarjan(int x){
	dfn[x] = low[x] = ++dfstime;
	for(int i=head[x];~i;i=nex[i]){
		int y = ver[i];
		if(!vis[i^1]){
			vis[i] = 1;
			if(!dfn[y]){
				pre[y] = x;
				tarjan(y);
				low[x] = min(low[x],low[y]);
				if(dfn[x] < low[y]){
					sum++;
					bridge[y] = true;
				}
			}else low[x] = min(low[x],dfn[y]);
		}else vis[i] = 1;
	}
}

void solve(){
	pre[1] = 1;
	for(int i=1;i<=n;i++)
	if(!dfn[i]) tarjan(i);
	for (int i = 1;i <= n;i++){
		if(bridge[i]) 
		printf("%d->%d",i,pre[i]);
	} 
}

第二版本(用来求删除桥中后边双连通中的点):

void tarjan(int x){
	dfn[x] = low[x] = ++dfstime;
	st.push(x);
	for(int i=head[x];~i;i=nex[i]){
		int y = ver[i];
		if(!vis[i^1]){
			vis[i] = 1;
			if(!dfn[y]){
				tarjan(y);
				low[x] = min(low[x],low[y]);
			}else low[x] = min(low[x],dfn[y]);
		}else vis[i] = 1;
	}
	int i;
	if(low[x] == dfn[x]){//桥不可能在多个桥双连通里,而点可能在多个点双连通里 
		colour++;
		do{
			i=st.top();st.pop();
			col[i]  = colour; //通桥双连通染色 
		}while(i!=x);
	}
}

模板题:桥

割点模板:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int head[N],ver[N],nex[N];
int n,m,cnt;
int dfn[N],low[N],dfstime,cut[N];
void add(int a,int b){
	ver[++cnt] = b;
	nex[cnt] = head[a];
	head[a] = cnt;
}
void read(){
	memset(head,-1,sizeof head);
	scanf("%d%d",&n,&m);
	for(int i=1,x,y;i<=m;i++){
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);
	}
}
void tarjan(int x,int root){
	dfn[x] = low[x] = ++dfstime;
	int tot = 0;
	for(int i=head[x];~i;i=nex[i]){
		int y = ver[i];
		if(!dfn[y]){
			tot++;
			tarjan(y,root);
			low[x] = min(low[x],low[y]);
			if((x==root && tot>1) || (x!=root && low[y]>= dfn[x])){
				cut[x] = 1;
			}
		}else{
			low[x] = min(low[x],dfn[y]);
		}
	}
}
int main(){
	read();
	for(int i=1;i<=n;i++) //这是为了防止原图不连通
	if(!dfn[i])
	tarjan(i,i);
	
	int ans = 0;
	for(int i=1;i<=n;i++)
	if(cut[i])
	ans++;
	printf("%d\n",ans);
	
	for(int i=1;i<=n;i++)
	if(cut[i])
	printf("%d ",i);
	return 0;
} 

割点模板题

点双连通

int low[N],dfn[N],cut[N];//cut记录割点
int root,dfstime,bt; //bt是一共多少块(多少连通块)
vector<int> block[N];// 连通块里点数
void tarjan(int x,int root){
	dfn[x] = low[x] = ++dfstime;
	int tot = 0;
	st.push(x);
	for(int i=head[x];~i;i=nex[i]){
		int y = ver[i];
		if(!dfn[y]){
			tot++;
			tarjan(y,root);
			low[x] = min(low[x],low[y]);
			if((x==root&& tot>1) || (x!=root && dfn[x]<=low[y] )) cut[x] = 1;//求割点的两种判断 
			if(dfn[x] <= low[y]){
				bt ++;
				block[bt].clear();
				int top;
				do{
					top = st.top();st.pop(); 
					block[bt].push_back(top);
				}while(y!=top);
				block[bt].push_back(x);  //重点:区分于桥双,点双的点可能多次出现在点双连通中 
			}
		}else{
			low[x] = min(low[x],dfn[y]);
		}
	}
}
int gdnum;//割点总数
void solve(){
	for(int i=1;i<=n;i++)
	if(!dfn[i]) tarjan(i,i);
	ll res = 0,num = 1;
	for(int i=1;i<=bt;i++){
		int gdnum = 0;
		int len = block[i].size();
		for(int j =0;j<len;j++){
			if(cut[block[i][j]]==1)
				gdnum ++;
		}
	}
}

下面给出题目:

例题:边双连通:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+100;
int n,m,cnt=1; //cnt从1开始,保证取反边 
int head[N],ver[N],nex[N],colour,top;
int dfn[N],low[N],dfstime,vis[N],du[N],col[N];
stack<int> st;
void add(int a,int b){
	ver[++cnt] = b;
	nex[cnt] = head[a];
	head[a] = cnt;
}
void read(){
	memset(head,-1,sizeof head);
	scanf("%d%d",&n,&m);
	for(int i=1,x,y;i<=m;i++){
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);
	}
}
void tarjan(int x){
	dfn[x] = low[x] = ++dfstime;
	st.push(x);
	for(int i=head[x];~i;i=nex[i]){
		int y = ver[i];
		if(!vis[i^1]){
			vis[i] = 1;
			if(!dfn[y]){
				tarjan(y);
				low[x] = min(low[x],low[y]);
			}else low[x] = min(low[x],dfn[y]);
		}else vis[i] = 1;
	}
	int i;
	if(low[x] == dfn[x]){//桥不可能在多个桥双连通里,而点可能在多个点双连通里 
		colour++;
		do{
			i=st.top();st.pop();
			col[i]  = colour; //通桥双连通染色 
		}while(i!=x);
	}
}
void solve(){	
	//tarjan(1);
	for(int i=1;i<=n;i++)
	if(!dfn[i]) tarjan(i);
	
	for(int x=1;x<=n;x++){
		for(int i=head[x];~i;i=nex[i]){
			if(vis[i^1]){ //树枝边,因为dfs不考虑双向边 
				vis[i] = 0;
				int y=ver[i];
				if(col[y] != col [x]){
					du[col[x]]++; //找到叶子节点 
					du[col[y]]++;
				}
			}else vis[i] = 0;
		}
	}
	int ans = 0;
	for(int i=1;i<=colour;i++){
		if(du[i]==1) ans++;
	}
	printf("%d\n",(ans+1)/2);//新建道路的数目是把原桥删去后桥双连通缩成点后 把每两个叶子上连边即可 
	//结论:当叶子节点=1,要+的边为0,否则为(叶子数+1)/2 
}
int main(){
	read();
	solve();
	return 0;
} 

点双连通

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e3;
int n,m,cs,cnt,root,dfstime,bt;
int nex[N],head[N],ver[N];
int low[N],dfn[N],cut[N];
vector<int> block[N];
stack<int> st;
void add(int x,int y){
	ver[++cnt] = y;
	nex[cnt] = head[x];
	head[x] = cnt;
}
void read(){
		for(int i=0;i<N;i++) cut[i] = dfn[i]=low[i]=nex[i] = ver[i] = 0,head[i] = -1;
		bt = dfstime = cnt = 0;
		while(st.size()) st.pop();
		for(int i = 1,x,y;i <= m;i ++){
			scanf("%d%d",&x,&y);
			n = max(n,max(x,y));//题目未给出最大点数 
			add(x,y);add(y,x);
		}	
}
void tarjan(int x,int root){
	dfn[x] = low[x] = ++dfstime;
	int tot = 0;
	st.push(x);
	for(int i=head[x];~i;i=nex[i]){
		int y = ver[i];
		if(!dfn[y]){
			tot++;
			tarjan(y,root);
			low[x] = min(low[x],low[y]);
			if((x==root&& tot>1) || (x!=root && dfn[x]<=low[y] )) cut[x] = 1;//求割点的两种判断 
			if(dfn[x] <= low[y]){
				bt ++;
				block[bt].clear();
				int top;
				do{
					top = st.top();st.pop(); 
					block[bt].push_back(top);
				}while(y!=top);
				block[bt].push_back(x);  //重点:区分于桥双,点双的点可能多次出现在点双连通中 
			}
		}else{
			low[x] = min(low[x],dfn[y]);
		}
	}
}
void solve(){
	ll res = 0,num = 1;
	for(int i=1;i<=bt;i++){
		int gdnum = 0;
		int len = block[i].size();
		for(int j =0;j<len;j++){
			if(cut[block[i][j]]==1)
				gdnum ++;
		}
		if(gdnum==0) res+=2,num = num*(len-1)*len/2;
		else if(gdnum==1) res++,num=num*(len-1);
	}
	printf("%lld %lld\n",res,num);
}
int main(){
	while(~scanf("%d",&m) && m){
		printf("Case %d: ",++cs);
		read();
		for(int i=1;i<=n;i++)
		if(!dfn[i]) tarjan(i,i);	
		solve();
	}
	return 0;
} 
桥 一个简单的例子 【有重边无向图求桥】 #include &lt;bits/stdc++.h&gt; using namespace std; #define N 400001 #define M 400001 #define forw(i,x) for(int i = fir[x];i;i = ne[i]) #define PER(i,a,b) for(int i = a; i&lt;= b... 阅读详情

相关推荐

Excel COUNTIF函数精确统计全解析:从模糊匹配到精准计数

在数据处理与办公自动化领域,条件计数是数据分析的基础操作,其核心原理在于对特定范围内满足设定条件的单元格进行识别与汇总。Excel中的COUNTIF函数是实现这一功能的常用工具,它通过文本匹配逻辑与通配符机制来执行条件判断。然而,其默认的模糊匹配行为常导致统计结果偏离预期,这正是精确统计的技术价值所在——确保数据汇总的准确性与可靠性,直接影响业务报告、薪酬核算、销售分析等应用场景的决策质量。本文聚焦COUNTIF函数的精确匹配技巧,深入剖析通配符(如星号*和问号?)的转义使用(通过波浪号~),并针对大小写敏

weixin_29040367的博客 353

图论:割点和桥

一、相关概念 1、点连通度:最小V的点数(一个图的点的连通度是最小割点集合中的顶点数) 2、边连通度:最小E的边数(一个图的边的连通度是最小割边集合中的顶点数) 3、割点:去掉割点这个图不连通(点连通度为1时,V的唯一元素) 4、割边(桥):去掉割边这个图不连通(边连通度为1时,E的唯一元素) 5、双连通图: 如果一个无向图的点连通度大于1,则是点双联通; 如果一个无向图的边连通度大...

weixin_30887919的博客 1009

CANoe_Demo_下载以及安装教程

CANoe Demo下载安装流程

Jar_Lee的博客 1万+

无向图的割点与桥

给定无向连通图G=(V,E); 割点: 若对于,从图中删去节点x与所有与x关联的边后,G分为两个或以上不相连的子图,则称x为G的割点。 割边: 若对于,从图中删去边e之后,G分为两个不相连的子图,则称e为桥或割边。 割边的判定法则: 无向边(x,y)是桥,当且仅当搜索树上存在x的一个子节点y,满足:dfn[x]<low[y] hdu4738 #include <bi...

Endeavor_G的博客 869

10xGenomics Loupe Browser实战指南:从数据导入到细胞注释全流程解析

本文提供了10xGenomics Loupe Browser的实战指南,详细解析了从数据导入到细胞注释的全流程。作为一款强大的可视化工具,Loupe Browser能帮助研究者直观探索单细胞测序数据,通过交互式操作进行细胞选择、差异基因分析和细胞类型注释,是单细胞数据分析入门和结果验证的高效平台。

blue42的博客 453

保姆级教程:断网环境下用Flexnet服务器搞定SolidWorks 2021安装与破解(附错误5解决方案)

本文提供SolidWorks 2021在断网环境下的企业级部署指南,详细解析Flexnet服务器本地化工作原理,并给出安装与破解的实战方案,特别针对常见的'错误5'问题提供多维度解决方案。适用于需要内网隔离或移动办公的工业设计场景,确保数据安全与授权合规。

weixin_28683391的博客 297

割点和桥的模板(割点和割边)

(1)割点与桥(割边)的定义(只存在于无向图) 割点:无向连通图中,去掉一个顶点及和它相邻的所有边,图中的连通分量数增加,则该顶点称为割点。 桥(割边):无向联通图中,去掉一条边,图中的连通分量数增加,则这条边,称为桥或者割边。 (2)割点与桥(割边)的关系 有割点不一定有桥,有桥一定存在割点;桥一定是割点依附的边。 (3)判断是否为割点 情况1:该点为根节点,那只要子节点数目超过1,...

HXX904的博客 1865

实战教程:如何用Python+小波变换+CNN搞定医学影像中的条纹噪声(附完整代码)

本文提供了一套完整的实战方案,指导如何利用Python结合小波变换与卷积神经网络(CNN)去除医学影像中的条纹噪声。该方法通过小波变换精准定位噪声,再使用轻量化CNN进行针对性清除,有效保护图像细节,并附有可运行的完整代码,为医学影像处理与AI分析提供高效工具。

weixin_29056101的博客 268

割点和桥学习

割点与桥(割边)的定义 割边和割点的定义仅限于无向图中 **割点:**无向连通图中,去掉一个顶点及和它相邻的所有边,图中的连通分量数增加,则该顶点称为割点。 **桥(割边):**无向联通图中,去掉一条边,图中的连通分量数增加,则这条边,称为桥或者割边。 割点与桥(割边)的关系: 1)有割点不一定有桥,有桥一定存在割点 2)桥一定是割点依附的边 暴力解决办法解决求解割点集和割边集 通过定义 去掉某...

qq_40492429的博客 2523

SAP后台JOB保姆级教程:从SM36创建到SM37监控,手把手教你搞定ABAP程序定时任务

本文详细解析SAP后台JOB从创建到监控的全流程,重点介绍SM36创建和SM37监控的操作步骤与最佳实践。通过真实案例演示如何配置定时任务、处理常见故障及实施企业级管理策略,帮助ABAP开发者高效管理后台程序执行。

weixin_30838873的博客 430

【Python_Zebra斑马打印机编程学习笔记(二)】基于BarTender将btw文件转换为zpl文件

本文介绍如何基于 BarTender 软件将 btw 格式的文件转换为 zpl 格式的文件,有需要的读者可以点赞收藏,也欢迎在评论区进行讨论。

禾戊之昂的博客 3375

桥和割点

#include&lt;bis/stdc++.h&gt; using namespace std; const int maxn=10000+10; typedef pair&lt;int,int&gt; Edge; int index=0,rootson=0; vector&lt;bool&gt; vis(maxn); vector&lt;int&gt; df...

cj1064789374的博客 268

Ubuntu零基础教学-如何把Ubuntu20.04界面从英文修改为中文?| 超级详细,建议收藏

带你如何把Ubuntu20.04界面从英文修改为中文?| 超级详细,建议收藏

**My Coding Family** 5340

割点和桥学习笔记

割点和桥 1.什么是割点和桥: 如果在图G中去掉一个顶点(自然同时去掉与该顶点相关联的所有边)后,该图的连通分支数增加,则称该顶点为G的割点(割顶)(cut-vertex)。 设无向图G=<V,E>,若存在E'⊆E使得p(G-E')>p(G),且对于任意的E''⊂E',均有p(G-E'')=p(G),则称E'是G的边割集,或简称为割集。若E'={e},则称e为割边或桥。...

weixin_33805557的博客 2616

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

割点和桥模板

寻找连通图的割点和桥用的也是tarjan算法,我们计算每个点不经过父亲能到达点的最小dfs序,如果是大于等于父亲的,则说明去掉父节点,该点即无法同上面连通,所以父节点是割点。桥类似,我们对于每个点标记它到父亲的那条边是否是桥。 cf1277E: 给出一个图求对于两点ab,有多少对xy使得从x到y的每一条路径都必经ab。 1 2 3 4...

rgndao的博客 285

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

无向图的割点和桥

定义 桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥。 割点:无向连通图中,如果删除某点后,图变成不连通,则称该点为割点。 在代码 dfsdfsdfs 过程中,加入“时间戳”, dfs−clockdfs-clockdfs−clock, 记录到达每个点的时间 pre[u] = ++dfs...

Stormjing的博客 1339

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

tarjan算法、割点和割桥,

tarjan算法是求一个图的强连通子图的 dfn[u]数组记录的这个节点入树的时间 low[u]数组记录的是以u为根节点的子树中最小的时间戳 步骤是:通过搜索不断的更新low和dfn数组,没当一条线搜索结束时,那么就会出现一个强连通子图,那么就回溯找根节点(dfn[u]==low[u]),并把这个强连通图给记录下来; const int maxn=1e5; int dfn[maxn],low[ma...

weixin_43310882 397

割点和桥 poj1144

前几天参加省赛了,无语凝咽。。。 又学了一年竟然还不如大一的时候,还是踏实点吧 割点和桥 简单的说就是去掉一个点或者一条边 原来的图变成了两个或者更多的图 vis[v]记录的是节点v当前的访问状态,1表示在栈中,0,表示未访问,2表示已经访问过; dfn[v]记录的是节点v被访问时的时间; low[v]记录的是点v可以到达的访问时间最早的祖先 在深搜的过程中,对于当前节点cur

曾经最动心的专栏 613

tarjan算法 (割点和桥)

最近刚学习了tarjan算法,发一篇博客写一下自己的心得和理解。 在了解割点和桥之前,我们先理解什么是双连通。 双连通和强连通分别是应用于无向图和有向图中的,那么在学习双连通之前,请自行学习求强连通分量的tarjan算法。 在一张连通的无向图中,如果删去任意的一条连接u,v的边,但u, v仍然可以保持连通,那么我们可以称u,v之间是边双连通的。 在一张连通的无向图中,如果删去任意的一个连接u,v的点,但u,v之间仍是连通的,那么我们可以称u,v之间是点双连通的。 接着我们来认识割点和桥 比如在这张图中,如

kaka03200的博客 770

tarjan解决割点和桥

对于某个无向图 割点又称割顶,如果删掉这个点,图不连通,那么这个点就是一个割点 桥、如果删掉这个边,图不连通,那么这个边就是一个桥   1、对于根节点,如果有一个以上子树,那么就是割点 2、对于非根节点,dfn[u]表示时间戳,即dfs到第几次访问到u点, low[u]表示顶点u及其子树中的点,通过非父子边(回边,即dfs树多出来的边),能够回溯到的最早的点(dfn最小)的dfn值 ...

这里RevolIA,_(:з」∠)_ 572
上一篇: 一本通->提高篇->图论-> 最小生成树:
下一篇: P3469 [POI2008]BLO-Blockade
A_Pathfinder
博客等级 码龄8年 29粉丝 90原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值