首页 > 其他分享 >Tarjan 求割点和桥

Tarjan 求割点和桥

时间:2023-08-29 12:00:39浏览次数:43  
标签:Tarjan 求割点 int 割点 dfs dfn low

欢迎批评指正!

前置芝士

  • 割点:对于一个点 \(u\),若删除 \(u\) 会使当前无向图中连通分量增多,我们就称 \(u\) 为该图的割点。
  • 桥(割边):同理,对于一条边 \((u,v)\),若删除 \((u,v)\) 会使当前无向图中连通分量增多,我们就称 \((u,v)\) 为该图的桥。
  • Tarjan 求强连通分量

Tarjan 求割点

设两个数组 \(dfn\) 和 \(low\),表示 dfs 序和仅通过 \(1\) 条非树边所能到达的点的最小 \(dfn\)
注意,这里的树边是有向边。
在 dfs 过程中维护这两个数组。

当 \(u\) 和其儿子 \(v\) 满足 \(low_v\ge dfn_u\) 时,称 \(u\) 是割点。
感性理解:因为这说明 \(v\) 无法通过非树边“逃出”\(u\) 的子树,只能通过 \(u\),那么当 \(u\) 被删除时,\(v\) 就与其他点脱离了联系。
但有一个特例:如果 \(u\) 是 dfs 树的根,那么只要有两个或更多儿子,\(u\) 就是割点,因为删除根节点后这两个或更多子树将互不相连。

算法流程

dfs 到 \(u\) 时:

  • 给 \(dfn_u\)、\(low_u\) 赋值。
  • 遍历每个子节点 \(v\):
    • 如果未被访问过,就先 dfs,然后更新 \(low_u=\min(low_u,low_v)\)。
    • 如果访问过,就更新 \(low_u=min(low_u,dfn_v)\)。
    • 如果你想知道为什么这样更新,请看这个
    • 如果满足 \(low_v\ge dfn_u\),将 \(u\) 标记为割点。但要特判根节点。

代码

int n,m;
vector<int> e[21145];// 边表
bitset<20008> cut;// 标记是否为割点

int dfn[21145],low[21145],cnt=1,root;// cnt:时间戳,root:当前 dfs 树的根
void tarjan(int u=root)
{
	int chd=0;// 孩子数量
	low[u]=dfn[u]=cnt++;
	for(int v:e[u])// 遍历所有孩子
	{
		if(!dfn[v])// 若未遍历过
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);// 更新 low
			if(low[v]>=dfn[u])// 判断是否为割点
			{
				cut[u]=true;
			}
			chd++;
		}
		else
		{
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(u==root)// 特判是否为根节点
	{
		if(chd>=2)
		{
			cut[u]=true;
		}
		else
		{
			cut[u]=false;
		}
	}
	return;
}

Tarjan 求桥

(未完待续)

标签:Tarjan,求割点,int,割点,dfs,dfn,low
From: https://www.cnblogs.com/chargedcreeper/p/tarjan-cut.html

相关文章

  • Tarjan 求强连通分量
    欢迎批评指正!前置芝士什么是强连通分量(\(\text{SCC}\))?强连通分量,一般指有向图的极大强连通子图,在这些子图中,所有点双向可达。dfs序:即dfs过程中访问点的顺序。dfs生成树:由dfs过程中访问的边组成的边集和原图的点集组成的树。树边,非树边:属于dfs过程中访问的边为......
  • tarjan
    割点与桥简介割点:对于一个无向图,如果把一个点及与其相连的边删除后这个图分裂为两个及两个以上不连通的子图,那么这个点就是这个图的割点(又称割顶)。割边:对于一个无向图,如果把一条边删除后这个图分裂为两个不连通的子图,那么这个点就是这个图的割边(又称桥)。tarjan求割点定理:如......
  • Tarjan基础用法
    \(\operatorname{Tarjan}\)基础用法目录\(\operatorname{Tarjan}\)基础用法\(\operatorname{Tarjan}\)求最近公共祖先前置芝士实现过程例题\(\operatorname{Tarjan}\)求割点、割边前置芝士\(\operatorname{Tarjan}\)求割点\(\operatorname{Tarjan}\)求割边例题\(\operatorn......
  • [Tarjan] 学习笔记
    原理强连通分量讲得超级屌,这次比董晓好得多voidtarjan(intx){ dfn[x]=low[x]=t++; s.push(x); in[x]=true; for(inti=h[x];i;i=e[i].next) { inty=e[i].to; if(!dfn[y]) { tarjan(y); low[x]=min(low[x],low[y]); } elseif(i......
  • Tarjan学习笔记
    TarjanTarjan算法是图论中非常常用的算法之一,能解决强连通分量,双连通分量,割点和桥,求最近公共祖先(LCA)等问题。Tarjan算法是基于深度优先搜索的算法,用于求解图的连通性问题。割点如果从图中删除节点\(x\)以及所有与\(x\)关联的边之后,图将被分成两个或两个以上的不相连的......
  • 强连通分量与tarjan算法
    强连通分量强连通:若一张有向图的节点两两之间可以互相抵达,那么这一张图是强连通的。强连通分量:极大的强连通子图。对图深度搜索的时候,每一个节点只访问一次,被访问过的节点与边构成搜索树。有向边按照访问的情况可以分为如下4类:1.树边:访问节点走过的边。2.返祖边:指向祖......
  • 【W的AC企划 - 第八期】tarjan缩点
    往期浏览第一期-博弈论(game)第二期-前缀和第三期-二分算法第四期-莫队算法第五期-线段树第六期-位运算(Bitmasks)第七期-树上分治第八期-Tarjan缩点第九期(拟)-树上启发式合并讲解(有向图)强连通分量缩点概念强连通分量缩点后的图称为SCC。有两种......
  • tarjan模板
    ilvoidtarjan(intu){ dfn[u]=low[u]=++num,st[++top]=u,ins[u]=1; G(i,u) { intv=ver[i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } elseif(ins[v])low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { intt=0; cnt++; do......
  • Tarjan 例题:洛谷P1407 [国家集训队] 稳定婚姻
    在洛谷中查看题意:自己读一下,大致就是\(2n\)个点,每个点编号为\(1-2n\),\(\lfloor编号/2\rfloor\)相同的点连条边。然后再给\(m\)条边。问:将每个\(\lfloor编号/2\rfloor\)相同的点间连的边断开,还能不能使每个编号为奇数的点都有一个编号为偶数的点对应。这个......
  • Tarjan
    我写这个随笔是让我更加理解算法,防止以后出错,因为我今天调Tarjan调了3个多小时,后来还是在大佬的帮忙下调出来了,问题不少先来看错误的(40pts): //缩点//https://www.luogu.com.cn/problem/P3387#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;con......