浅谈 Tarjan 求连通分量中的 low 与 dfn
lalaji2010 · · 算法·理论
这篇文章能够帮助你什么
首先,你需要基本掌握 DFS 树的性质,Tarjan 求三个连通分量(强连通、边双、点双)的算法原理。而这篇文章仅针对其中一个常常令初学者困惑的点,也就是下面这行代码:
low[u]=min(low[u],dfn[v]);
为什么写
1.在 Tarjan 算法中的定义
在 Tarjan 算法中,我们定义
注:无向图 DFS 树无横叉边,而有向图强连通分量由当前子树走到横叉边指向的子树(该子树先前一定遍历过,这是横叉边的定义)一定无法走回(若能走回,则一定早在横叉边指向的子树时走到当前子树)。
并且若
由这个定义,我们可以理解 low[u]=min(low[u],dfn[v]); 的正确性。
2.疑惑点
再看这个式子:low[u]=min(low[u],dfn[v]);。我们理解 ta 是正确的,但是我们质疑 ta 是不是唯一正确的。其中最有迷惑性的疑惑就是:我们将
先说结论:上述改写在点双连通分量求解中是错误的,而在强连通分量和边双连通分量求解中是正确的。
我们来研究一下原理。
Ⅰ 强连通分量
我们对于有向图
在原算法中,当我们遍历结点
当我们改换写法后,
-
若
v 走一步先到w->v 上另一点vv ,做代换v'=vv ,再讨论v' 走法,等价于讨论v 。我们只需证明在其他分类中的正确性即可。 -
若
v 走一步先到u ,再通过u 走上u 的祖先,则显然u 向v 的链上的点都能够走到v 上面。这样写没有问题。而原写法是只标记low[u] 防止弹出链u->v 。两个写法实现同样的目的。 -
若
v 走一步直接到u 的祖先,该写法完全能够包含。
综上,强连通分量正确。
Ⅱ 点双连通分量
我们对于无向图
在原算法中,当我们遍历结点
当我们改换写法后,
-
若
v 走一步先到w 子树内另一点vv ,做代换v'=vv ,再讨论v' 走法,等价于讨论v 。我们只需证明在其他分类中的正确性即可。 -
若
v 走一步先到u ,再通过u 走上u 的祖先。原写法只能走到u 。若u 是割点,原写法正确,而改后的写法却会认为v 可以走出去,错误。 -
若
v 走一步直接到u 的祖先,该写法没有影响。
综上,点双错误。
Ⅲ 边双连通分量
我们对于无向图
在原算法中,当我们遍历结点
当我们改换写法后,
-
若
v 走一步先到w 子树内另一点vv ,做代换v'=vv ,再讨论v' 走法,等价于讨论v 。我们只需证明在其他分类中的正确性即可。 -
若
v 走一步先到u ,再通过u 走上u 的祖先。原写法只是走到u 。考虑删掉边(u,w) ,这个操作并不会影响我们走到u ,不影响正确性。 -
若
v 走一步直接到u 的祖先,该写法没有影响。
综上,边双正确。