Kosaraju算法——关于图的后序遍历的特征

新博客地址: http://hanjc.me/blog/2014/01/04/postordering-dfs/

Kosaraju算法是一种常见的求图的强联通分量的算法,该算法先从任意结点开始对原图G进行一次DFS后序遍历,之后依据第一次DFS的结果的反向序列(即根据reverse postordering),对原图的反向图G’进行前序的DFS。在第二次DFS中,每个联通分量即为一个强联通分量。

算法是很简单,不过之前并没有完全搞明白,昨天晚上仔细想了下,总算弄明白了。事实上后序遍历一个图得到的序列包含了原图重要的结构信息,正是这些结构信息保证了第二次DFS能得到正确的结果。

 

先简单阐述结论,第一次后序遍历是为了保证,在第二次对反向图的前序遍历中,先访问到的强联通分量不指向任何未被访问到的强联通分量

下面将简单证明一下。

假设一个图G,共有m个结点V1, V2, ..., VmG的一个强联通分量为S,包含n个结点。从任意结点开始对G进行一次后序遍历,得到后序序列A1, A2, ..., Am。在这个序列中,我们可以找到这样一个最短的连续子序列Ai, Ai+1, ..., Aj,使得S中所有的结点都包含在该子序列中,那么该子序列将满足如下两点:

  1. 结点集合{A1, A2, ..., Ai-1}不指向S(即不存在一条边从{A1, A2, ..., Ai-1}中任意一个结点指向S中的某个结点)
  2. S不指向结点集合{Aj+1, Aj+2, ..., Am}

这两点非常容易证明,我们知道S是一个强联通分量,S作为一个整体与其他任意的结点都只有单向的边,即对于任意不属于S的结点v,不可能同时存在v指向S的边和S指向v的边(否则强联通分量就是{S+v}了)。集合{A1, A2, ..., Ai-1}和集合{Aj+1, Aj+2, ..., Am}中的所有结点都满足这一条件。

我们先证明第一点,对于集合{A1, A2, ..., Ai-1}中任意结点Vk(1<=k<=i-1),如果Vk指向S,那么当访问到Vk的时候必然会遍历Vk指向S的那条边(注意如果Vk指向S,那么就不可能有S指向Vk的边了),而S是一个强联通分量,访问其中任一结点最终都会访问到整个S,那么在后序序列中,Vk必然出现在包含S的子序列的后边,这与Vk属于{A1, A2, ..., Ai-1}这一条件相左,因此这种情况是不可能出现的。

利用相似的思想我们可以证明第二点。

那么这两条性质对于Kosaraju算法中的第二次DFS有什么作用的?不要忘记在Kosaraju算法中还有重要的一步,那就是第二次DFS是在原始图的逆向图(结点与原图相同,边与原图的边方向相反)上进行的!所以我们第一次DFS得到的后序序列,在反向图上就会呈现出相反的特性:

  1. S不指向结点集合{A1, A2, ..., Ai-1}
  2. 结点集合{Aj+1, Aj+2, ..., Am}不指向S

考虑结点Am所在的强联通分量,假设包含该强联通分量的最短子序列为Ak, Ak+1, ..., Am,那么套用刚刚提到的特性1,我们有如下结论:在反向图中,Am所在的强联通分量不指向任何其他的强联通分量。所以从Am开始对反向图进行一次前序遍历,所有能访问到的结点均属于同一个强联通分量。接下来就是一个递归的过程了,标记了Am所在的强联通分量中所有的结点之后,剩下的序列满足与原始序列同样的性质,因此只需要逆着后序序列依次对反向图进行前序遍历,就能求得所有的强联通分量。因此,在第二次DFS的过程中,每访问到一个新的强联通分量,总能保证这个强联通分量没有指向未访问的强联通分量的边

突然有个想法,可惜时间不够了,先留着吧:这个算法是不是可以用来做拓扑排序?

posted @ 2014-01-09 10:24  Zealoct  阅读(938)  评论(0编辑  收藏  举报