图的连通性——Tarjan算法&割边&割点
tarjan算法
原理:
我们考虑 DFS 搜索树与强连通分量之间的关系。
如果结点 是某个强连通分量在搜索树中遇到的第⼀个结点,那么这个强连通分量的其余结点肯定 是在搜索树中以 为根的⼦树中。 被称为这个强连通分量的根。
反证法:假设有个结点 在该强连通分量中但是不在以 为根的⼦树中,那么 到 的路径中肯 定有⼀条离开⼦树的边。但是这样的边只可能是横叉边或者反祖边,然⽽这两条边都要求指向的结点已 经被访问过了,这就和 是第⼀个访问的结点⽭盾了。得证。
思路:
在 Tarjan 算法中为每个结点 维护了以下⼏个变量:
1:dfn[u]深度优先搜索遍历时结点 的DFS序。
2:low[u]设以u为根的⼦树为Subtree[u]。low[u]定义为以下结点的dfn的最⼩值:
Subtree(u)中的结点;从 Subtree(u)通过⼀条不在搜索树上的边能到达的结点。
遍历时维护栈,⽤于求解强连通分量。 ⼀个结点的⼦树内结点的 dfn 都⼤于该结点的 dfn。 从根开始的⼀条路径上的 dfn 严格递增,low 严格⾮降。 按照深度优先搜索算法搜索的次序对图中所有的结点进⾏搜索。
在搜索过程中,对于结点u和与其v相邻的结点 考虑 3 种情况:
-
v未被访问:继续对v进⾏深度搜索。在回溯过程中,low[v]⽤low[u]更新 。因为存在从u到v的直接路径,所以v 能够回溯到的已经在栈中的结点,u也⼀定能够回溯到。
-
v被访问过,已经在栈中:即已经被访问过,根据low值的定义(能够回溯到的最早的已经在栈中 的结点),则⽤dfn[u]更新low[v] 。
-
v被访问过,已不在在栈中:说明v已搜索完毕,其所在连通分量已被处理,所以不⽤对其做操作。

浙公网安备 33010602011771号