Tarjan Tarjan算法

问题

用Tarjan算法求有向图DGDG的所有强连通分支。

解法

Tarjan算法通过定义强连通分支的根节点,来求出有向图DGDG的所有强连通分支。有向图DG=<V,E>DG = <V,E>中一个强连通分支中的根节点是该强连通分支中下标最小的顶点,也是该强连通分支中所有顶点通过DFS能够搜索到的下标最小的顶点。

indexindex为顶点下标,lowlinklowlink为该顶点所属强连通分支的根节点下标,显然属于同一个强连通分支的所有顶点lowlinklowlink值相等。同一个强连通分支中的所有顶点满足indexilowlinkiindex_i \geq lowlink_i,强连通分支的根节点满足indexroot=lowlinkrootindex_{root} = lowlink_{root},其他顶点则满足indexi>lowlinkiindex_i \gt lowlink_i

Tarjan算法按照以下几步操作:

(1)(1) 初始时设任意顶点viv_i的强连通分支的根节点指向自己,即father(i)=ifather(i) = i,Tarjan的根节点和Kosaraju中并查集的父节点含义完全相同,因此也用父指针表示;

(2)(2) 用DFS算法搜索有向图DGDG的所有顶点,得到每个顶点的lowlinklowlink,并按照搜索顺序将顶点推入堆栈StackStack(先入后出);

(3)(3) 从堆栈StackStack中依次取出每个顶点(即逆序遍历DFS搜索到的所有顶点)viv_i,判断其是否为根节点(indexi=lowlinkiindex_i = lowlink_i)。若出栈顶点viv_i是根节点,则在viv_i之前出栈的且未分配到其他强连通分支的顶点(father(j)=jfather(j) = j的顶点vjv_j即为未分配的顶点),都属于以viv_i为根节点的强连通分支,设置father(j)=ifather(j) = i;若出栈顶点viv_i不是根节点,则等待根节点vjv_jviv_i属于以vjv_j为根节点的强连通分支;

该算法时间复杂度为O(V+E)O(\| V \| + \| E \|)

Tarjan Algorithm

Introduction To Algorithms

源码

Tarjan.h

Tarjan.cpp

测试

TarjanTest.cpp

Last updated