Tarjan算法由 Tarjan, R. E. 在1972年提出。
它基於圖的DFS( depth first search ),複雜度爲 O(V+E) ,可以被看作是線性時間算法。
這篇文章的目的在於總結Tarjan算法在求解強連通分量,橋、割方面的應用。尚未完成,逐漸更新。
強連通分量的討論
強連通分量的定義
強連通分量是有向圖中的概念。
強連通分量( strongly connected components ),簡稱 SSC 。其名稱中的分量( components )二字,不是數學意義上(比如向量)的分量,更加靠近「部件」之義。不需要糾結於名稱。
試做如下定義:
在有向圖
G
中,考慮一個頂點集合
- Sv 中任意頂點,都能經由 G 上的邊相互到達。
包含
這個集合可以只有一個元素。可以這麼理解:「自己」已經到達了「自己」,所以單個頂點的集合,也算是強連通分量。
下圖就存在3個強連通分量:
我們發現,其實一個有向圖 G 的強連通分量可以有很多種。
以下兩組都是符合上述定義的強連通分量:
{1},{2},{3},{4},{5},{6} - {1,5,6},{1,2,5},{3},{4}
但是這並不是我們想要的「強連通分量」,它不符合直覺。第一組沒有任何意義,第二組頂點重複了。
所以我們需要加強一下定義,得到最大而且不重複的「強連通分量」:
在有向圖 G 中,考慮一個頂點集合
Sv 。 Sv 有兩個性質:- Sv 中任意頂點,都能經由 G 上的邊相互到達。
- 已不能加入其他頂點,使這個集合的元素數量增加。
包含
Sv 所有頂點,且包含這些頂點之間相連的所有邊的子圖就是有向圖 G 的「強連通分量」。根據新的定義,每一個強連通分量集合都是最大化了的,自然不會重複。
這種定義符合直覺,且比較容易理解。
強聯通分量與「環」 (更新時間:2017.6.5) 在「強連通分量的定義」一節中,我們已經用「強連通分量」的「頂點集」即
Sv 來標識一個「強連通分量」.不妨從頂點的角度繼續研究,以獲得求解「強連通分量」的算法.
考慮 Sv={1,2} .頂點 1 和頂點
2 由兩條邊连结.我們畫出下面這個示意圖.
然後做如下思考:
頂點 1 和頂點
2 及相应的边是否形成了一個環.對於一個普通的有向圖, 它的「強連通分量」和由這個圖上的邊組成的環有何關聯.
經過上述思考, 你應當發現:
在有向圖中, 一個環中的頂點必然在同一個「強連通分量」中.
那麼,我們就可以有如下的樸素思想:
若有向圖的一個頂點在若干個環中, 那將這些環上的所有頂點都放進同一「強連通分量」的頂點集中.
因此,求解「強連通分量」的過程 即可以看成 有向圖 「尋環」 的過程.
並且,因爲一個頂點只可能在一個強連通分量中, 可以用強連通分量中的某一個頂點的編號來標識這個強連通分量.
強連通分量的求解
Tarjan算法能求解強連通分量。
Tarjan尋環的直觀理解 (更新時間:2017.6.5) 一個有向圖的DFS樹(即依據有向圖的DFS過程中,頂點被訪問的先後次序構成的樹狀結構)中,邊能被分爲3類.
如下圖所示.
- 第1類:返祖邊(綠色).從一個節點指向這個節點的祖先的邊.這種邊產生環.
- 第2類:橫叉邊(橙色).從一棵子樹指向另一棵子樹的邊.這種邊不產生環.
- 第3類:普通邊(黑色).非第1類和第2類的邊.這種邊也不產生環.
也就是說,Tarjan算法要尋找的,其實就是「返祖邊」.
返祖邊帶來環,而環就帶來了強連通分量.
現在Tarjan算法能夠簡單地理解如下:
在DFS的同時,不斷地把路徑上的頂點編號壓入棧中,檢測每條邊是否指向當前節點的祖先.若:
- 是當前節點的祖先:即探測到環.把環上所有頂點歸入以祖先標識的強聯通分量.
- 不是當前節點的祖先:繼續DFS.
Tarjan算法的實現以及註解(未完成~) wwww
參考文章: