系列文章目录
前言
第一次写算法,讲得肯不透彻,有误还请指教awa
一、回顾
先来回顾一下dfs的基本框架:
//存图方式:vector(g[N])
void dfs(int u){
//u:当前节点
vis[u]=true;
for(int& v:g[u]){
//访问u连到的每个节点
if(!vis[v]) dfs(v);
}
}
二、tarjan算法
请注意,这里讲的仅限于无向图,有向图的算法会稍有不同。
- 首先我们可以确定的是回边一定不是桥1。
- 那么就只需要判断树边了。
回顾割边的定义,删边后两端断开,那么就意味着一端的点永远无法通过一条路径回到另一端,在DFS-tree上就体现为下方的节点永远无法通过非树边回到上方的点。如果成立,即只能通过树边相连,那么这条树边就是桥了!(因为是树,每个节点以自己为终点只会有一个直系父亲)
tarjan算法定义了两个数组:depth[]
和low[]
,定义如下:
depth[i]
:节点i在DFS-tree上的深度。low[i]
:在dfs-tree上,以节点i及其子孙为起点的回边回到的 最低 高度。
假设我们已经算出每个节点的depth
(下简称dep
)和low
,如何判断割边呢?
(务必注意,dep
和low
越大意味着越晚被遍历)
分类讨论一下吧:(假设目前在处理tree2上u->v边)
-
l o w [ v ] < = d e p [ u ] low[v]<=dep[u] lo