对tarjan缩点/求割点/求桥的理解

不适合初学者,适合复习

缩点

dfn[i]dfn[i]就是一个dfsdfs序。
low[i]low[i]ii不通过ii的父亲节点能到达的最高(深度最小/dfsdfs序最小)的祖先节点。
上面两个数组初始化都是dfsdfs序编号;解释:dfn[i]dfn[i]显然,一开始每个点的low[i]low[i]就是自己,也是dfsdfs序。
然后遍历与之相邻的点:

  • 如果这个点之前没被访问过,就先继续往下递归,回溯回来时用下面点的low[]low[]更新当前这个点的low[]low[],取下面点low[]low[]的最小值,因为这个点可以走到这些点,按照low[]low[]的定义需要取minmin
  • 如果这个点被访问过,那就直接用栈里(已经求出的强连通分量)的点的low[]low[]更新当前点的low[]low[],因为这个点可以到达这些点(因为栈里的点已经是求出的一个强连通分量)。

遍历完这些点之后如果当前节点的low[]=dfn[]low[]=dfn[],那就说明这个节点的子节点已经没有返祖边了,当前点和当前点的子节点都没有边指向更早的祖先,所以说这个点当前的强连通分量是最大的(为什么求出的强连通分量是最大的)。
记录从栈里弹出来的点就是一个强连通分量(环),然后就可以缩点了。
注意图不一定联通,所以要对每个没搜过的点都跑一遍,判断dfn[]dfn[]是否有值即可。

割点与桥的判断

割点和桥是对于无向图而言的。
有割点不一定有桥但有桥一定有割点,可以自己画图尝试一下。
对于割点,如果当前节点frfr的子树里有一个节点vv必须通过当前节点frfr才能访问到frfr的祖先借节点,那么frfr就是一个割点,因为去掉frfr之后vv就与frfr上面的点不连通了。
也就是在回溯回来时判断dfn[fr]<=low[v]dfn[fr]<=low[v],根节点要单独考虑,看是否有一棵以上子树即可。
桥与割点只是点与边的区别,桥就是判断dfn[fr]<low[v]dfn[fr]<low[v],去掉了相等的情况。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章