图论---割点,割边与双连通分量

割点和割边

割点与割边是在无向图中讨论的问题。
割点,即删除某个顶点,原图不再连通,这样的顶点称为割点。有时候也叫 “割顶”。割边是与割点性质类似的边(有时候叫做 “桥”)。求割点和割边同样利用Tarjan算法的 dfn[ ]数组和 low[ ]数组。
注意由于不同于求强连通分量,割点和割边是无向图上的问题,因此 low[ ] 数组的含义有细微变化,见后文。

Tarjan算法求割点

在Tarjan算法求强连通分量的过程中,讨论了 dfn[i] = low[i] 的情况,这意味着结点 i 不能通过其子孙结点回到更早的时间戳了,也就是说顶点 i 是一个强连通分量的起点。
同样也可以用 dfn[i] 和 low[i] 的关系,确定顶点 i 是否为割点。
分以下两种情况:

  1. 顶点 u 是搜索树的根节点。
    此时,如果在搜索树中,顶点 u 有两个以上的孩子。则顶点 u 一定是割点,因为此时如果去掉顶点 u ,那么其不同子树之间的结点必定不可到达。
  2. 顶点 u 不是搜索树的根节点。
    此时,如果对于边 (u,v)如果 low[v] >= dfn[u],则说明结点u是一个割点。

low[v] >= dfn[u],意味着结点v不能通过除边(u,v)以外的边回到其搜索树中的祖先结点,那么当去掉结点u时,结点v便会和其祖先结点分开。此时结点u就是一个割点。

代码

void Tarjan(int u, int fa)
{
	dfn[u] = ++dfs_clock;
	low[u] = dfn[u];
	int child = 0;
	for(int i=head[u];i;i=edge[i].next)
	{
		int v = edge[i].to;
		if(!dfn[v])
		{
			child++;
			Tarjan(v, u);
			low[u] = min(low[u], low[v]);
			if(low[v]>=dfn[u])
			{
				iscut[u] = 1;
			}
		}
		else if(dfn[v]<dfn[u]&&v!=fa)
		    low[u] = min(low[u], dfn[v]);
	}
	if(fa==-1&&child==1)
	    iscut[u] = 0;
}

关于到底是 low[u] = min(low[u],dfn[v]) 还是 low[u] = min(low[u],low[v]) 的问题,求强连通分量时,两种写法都可以,但是求割点时只有 low[u] = min(low[u],dfn[v]) 是正确的,具体原因我目前也没明白。所以最好统一一下,都写成 low[u] = min(low[u],dfn[v])

Tarjan算法求割边

基本思路与求割点一致,当一条边(u,v),有 low[v] > dfn[u],则如果不经过边(u,v),顶点v不能访问到更早的时间戳,边(u,v)是一条割边。

int Tarjan(int u, int fa)
{
	dfn[u] = ++deep;
	int lowu = dfn[u], child = 0;
	int sz = G[u].size();
	for(int i=0;i<sz;i++)
	{
		int v = G[u][i];
		if(dfn[v]==0)
		{
			int lowv = Tarjan(v, u);
			lowu = MIN(lowu, lowv);
			if(lowv>dfn[u])
			{
				int from = u, to = v;
				if(from>to)     //做了一个从小序号开始大序号结束的处理
				{
					int t = from;
					from = to;
					to = t;
				}
				bridge[++pb].from = from;
				bridge[pb].to = to;
			}
		}
		else
		{
			if(v!=fa&&dfn[v]<dfn[u])
			    lowu = MIN(lowu, dfn[v]);
		}
	} 
	low[u] = lowu;
	return lowu;
}

双连通分量

针对无向图,有一个类似有向图强连通分量的定义叫做双连通分量,分为 “点双连通分量” 和 “边双连通分量”。

点双连通分量是原图的一个极大子图,其中任意两点都至少存在两条点不重复路径,也就是说这是一个没有割点的极大子图。特殊的,离散的顶点,和两点一边的联通分量也属于点双连通分量,因为这些联通分量也没有割点。
点双连通分量的性质:

  1. 点双连通分量内部的任意两条边都在同一个简单环中。
  2. 不同的点双连通分量,有且只有一个公共点,且这个点一定是原图的割点。
  3. 任意割点都是至少两个不同点双连通分量的公共点。

边双连通分量是一个没有割边(桥)的极大联通子图。离散的点是边双连通分量,但两点一边组成的联通分量不是,因为其具有割边。
边双连通分量具有下面的性质:
4. 从原图中去掉所有割边,剩下的联通分量为双连通分量。
5. 不同的边双连通分量之间没有公共点和边。

由于双连通分量是利用割点和割边定义的,所以求双连通分量的过程就是求割点和割边的过程,关键在如何保存信息,这一点需要按照具体题目来分析。

例题

求割点模板:
洛谷P3388 【模板】割点(割顶).
UVA315 Network.

求割边模板:洛谷P1656 炸铁路.

求去掉一个点,能得到多少连通块: 2020ICPC·小米 网络选拔赛第一场:D - Router Mesh.

并查集+点双连通分量:HDU3749 Financial Crisis.

思维+点双连通分量:洛谷P3225 [HNOI2012]矿场搭建.

边双连通分量模板:洛谷T103489 【模板】边双连通分量.

图论综合题,涉及双联通分量,思维难度较大:
ACM-ICPC CERC 2015 Juice Junctions.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值