首页 > 其他分享 >简单易懂的 Tarjan求割点与桥 详解

简单易懂的 Tarjan求割点与桥 详解

时间:2022-10-11 20:55:55浏览次数:56  
标签:Tarjan 连通 求割点 割点 dfn low 易懂 114514 节点

一些简单的概念

连通分量:无向图G的极大连通子图称为G的连通分量

说人话:把无向图G分成几块,满足每一块内都是连通的,且几个块之间不连通,这些块就是G的连通分量

割点:无向连通图中,去掉一个顶点及和它相邻的所有边,图中的连通分量数增加,则该顶点称为割点。

说人话:如果去掉这个点,原来连通的某一块不连通了,那这个点就是割点

割边/桥:无向联通图中,去掉一条边,图中的连通分量数增加,则这条边称为割边或者桥

说人话:如果去掉这条边,这条边连着的两个点就不连通了,那这条边是割边/桥

比如下图:点1和点4为割点,边 1-4 为桥

那么我们如何求一张图的割点和桥呢?

Tarjan

(为了方便,以下先假设图连通)

割点

在一张图上跑dfs,由于访问过的点不会重复访问,显然把搜索过程中经过的所有边和点合起来会构成一棵树,这棵树被叫做搜索树,在这棵树上的边会被称作树边。
比如上一张图的搜索树如下:

如果一个点 \(u\) 为割点,也即该点被去掉了会影响图的连通性,那么必然满足:至少存在 \(u\) 的一个孩子节点 \(v\),使得在原图上从 \(v\) 出发,不经过 \(u\) 无法到达不在 \(u\) 子树上的其他点

比如在这棵树中,5、6在原图上不通过4不可能到达1、2、3三个点,所以4为割点

至于没有根节点的父节点,之后再额外做讨论

那么如何找到满足条件的点呢?这就要用到Tarjan了。

Tarjan定义了两个数组:

dfn[x]:表示在dfs过程中x是第几个被遍历到的,即dfs的时间戳。注意:如果dfn[x]>dfn[y],这说明y必然不在x的子树上
low[x]:表示x不经过父节点的情况下,所能到达的dfn最小的节点。(事实上并不保证dfn一定最小,但这样可以方便理解)

在搜索过程中:

low[x]初始化为dfn[x]。
对于x的父节点,我们跳过它即可
在搜索的过程中,对于x的子节点y,x可以直接通过y到达low[y],即low[x]=min(low[x],low[y])。
对于其他与x相连的点y,x到达low[y]的过程中不能保证不会经过x的父亲,所以我们只能让low[x]=min(low[x],dfn[y])。

最后是判断割点:

由于,在不经过非根节点x的情况下,如果x的孩子节点y能够到达某一不在x的子树上的节点,那么它必然能通过树上的边到达某一dfn值小于x的节点,也就是说必然满足low[y]<low[x]
反之,如果low[x]>=low[y],则y必然不能在不通过x的情况下到达其他点
也就是说,如果存在x的儿子节点y,使得low[x]>=low[y],则x为割点

当然,前提是这个点并非是根。如果是根的话,我们另外进行判断。
如果根节点的两棵子树通过某条边相连,那么我们必然在dfs的过程中必然能通过该边从一棵子树到另一棵子树,那两棵子树就变成一棵了。所以只要根节点有两棵或以上的子树,就说明两棵子树没有其他边相连,根节点即为割点


请注意:以上只是对于Tarjan的概述,只能方便理解,但仍然有不少漏洞,并非严谨证明。只不过足够我们AC了

与割点几乎一致的思路。如果一条边是桥,那么我们必然无法在不通过这条边的情况下到达其他点——只不过我们这次还加了一个限制:由于不让通过那条边,我们现在连根节点都去不了

所以当节点x有子节点y满足low[y]>dfn[x],就说明不能不通过(x,y)到达其他点,就说明(x,y)为桥

上代码

vector<int> s[114514];
int de,cnt;
int dfn[114514],low[114514],vis[114514];
int is_cut[114514],is_bri[114514];
void dfs(int x,int fa){
	de++;
	low[x]=dfn[x]=de;
	vis[x]=1;
	for(int y:s[x]){
		if(y==fa) continue;
		if(vis[y]==0){
			dfs(y,x);
			low[x]=min(low[y],low[x]);
			if(!fa){
				cnt++;
				if(cnt>=2) is_cut[x]=1; //对根进行特判 
			}
			else if(low[y]>=dfn[x]) is_cut[x]=1;
			if(low[y]>dfn[x]) is_bri[y]=1;//is_bri[i]代表i与其父亲的连边是否为桥
		}
		else 
			low[x]=min(low[x],dfn[y]);
	}
}

标签:Tarjan,连通,求割点,割点,dfn,low,易懂,114514,节点
From: https://www.cnblogs.com/WhangZjian/p/16773630.html

相关文章

  • 洛谷 P3530 / bzoj2788【tarjan】【差分约束】
    判断是否有解可以使用差分约束。求解赛车手的成绩的取值可以使用Floyd。但是\(O(n^3)\)会TLE。可以先进行一次缩点。然后进行Floyd求出每一个连通块内的最长路径......
  • 简单易懂的讲解深度学习(入门系列之一)
    公众号ID|ComputerVisionGzq学习群|扫码在主页获取加入方式计算机视觉研究院专栏作者:Edison_G目前人工智能非常火爆,而深度学习则是引领这一火爆现场的“火箭”。目前人工智能......
  • 【复习笔记】tarjan算法
    写点东西好复习,主要是tarjan这个东西学了容易忘,忘了也不难捡起来,但捡起来了又容易忘。tarjan的前置知识dfs树就暂且咕咕了,因为这东西没什么模板,变化挺多的,估计是写不完。......
  • Tarjan算法
    二、无向图的割点与桥什么是无向图?简单来说,若一个图中每条边都是无方向的,则称为无向图。割点若从图中删除节点x以及所有与x关联的边之后,图将被分成两个或两个以上的......
  • tarjan
    终于来到了差点让我破防的tarjan争取说明白吧定义:1.桥:指去掉该边,其原本所在的强连通分量变为两部分(即不再是强连通分量)2.边双连通分量:即没有桥的无向连通图3.强......
  • java入门基础 static final 关键字 修饰符 解释(通俗易懂)
    final和static和finalstatic区别解释?static是用来修饰静态资源的(包括类、方法、变量等),final是用来保证当前变量为常量,finalstatic即保证为静态常量(意思就是不依......
  • Luogu P3469 [POI2008]BLO-Blockade(tarjan求割点)
    题目链接:https://www.luogu.com.cn/problem/P3469 [POI2008]BLO-Blockade题面翻译B城有$n$个城镇,$m$条双向道路。每条道路连结两个不同的城镇,没有重复的道路,所有......
  • 简单易懂的manacher算法讲解
    manacher求最长回文子串的算法(顺便还能求出来以每个点为中心的最长回文子串)介绍先来一道模板题:P3805【模板】manacher算法先考虑一下小学二年级都会的纯暴力解法:以每......
  • TCP三次握手(通俗易懂)
    一--导读TCP服务器的传输控制块: 指向发送和接收缓存的指针(管发和收的人)指向重传队列的指针(重新发送的人)当前的发送和接收序号(管现在发多少和收多少的人)  二---TCP连接要......
  • Tarjan
    P3387【模板】缩点(强连通分量+拓扑+dp)#include<iostream>#include<queue>#include<cmath>#definefor1(i,a,b)for(inti=a;i<=b;i++)#definemp(a,b)make_pai......