Tarjan演算法
Tarjan演算法(以發現者Robert Tarjan[1]命名)是一個在圖中尋找強連通分量的演算法。雖然發表時間更早,它仍可以被視為Kosaraju演算法的一個改進。它的效率跟Gabow演算法差不多。
概述
此演算法以一個有向圖作為輸入,並按照所在的強連通分量給出其頂點集的一個劃分。圖中的每個節點只在一個強連通分量中出現,即使是在有些節點單獨構成一個強連通分量的情況下(比如圖中出現了樹形結構或孤立節點)。
演算法的基本思想如下:任選一節點開始進行深度優先搜尋(若深度優先搜尋結束後仍有未訪問的節點,則再從中任選一點再次進行)。搜尋過程中已訪問的節點不再訪問。搜尋樹的若干子樹構成了圖的強連通分量。
節點按照被訪問的順序存入堆疊中。從搜尋樹的子樹返回至一個節點時,檢查該節點是否是某一強連通分量的根節點(見下)並將其從堆疊中刪除。如果某節點是強連通分量的根,則在它之前出堆疊且還不屬於其他強連通分量的節點構成了該節點所在的強連通分量。
根節點的性質
演算法的關鍵在於如何判定某節點是否是強連通分量的根。注意「強連通分量的根」這一說法僅針對此演算法,事實上強連通分量是沒有特定的「根」的。在這裡根節點指深度優先搜尋時強連通分量中首個被訪問的節點。
為找到根節點,我們給每個節點v一個深度優先搜尋標號v.index,表示它是第幾個被訪問的節點(時間戳)。此外,每個節點v還有一個值v.lowlink,表示從v出發經有向邊可到達的所有節點中最小的index(追溯值)。顯然v.lowlink總是不大於v.index,且當從v出發經有向邊不能到達其他index值更小的節點時,這兩個值相等。 v.lowlink在深度優先搜尋的過程中求得,v是強連通分量的根若且唯若v.lowlink = v.index。
虛擬碼
algorithm tarjan is input: 图 G = (V, E) output: 以所在的强连通分量划分的顶点集合 index := 0 S = empty // 初始化栈S为空栈 for each v in V do if (v.index is undefined) strongconnect(v) end if function strongconnect(v) // 将未使用的最小index值作作为节点v的index v.index := index v.lowlink = index index := index + 1 S.push(v) // 考虑节点v的后继节点 for each (v, w) in E do if (w.index is undefined) then // 后继节点w未访问,递归调用 strongconnect(w) v.lowlink = min(v.lowlink, w.lowlink) else if (w is in S) then // w已在栈S中,则其也在当前的强连通分量中 v.lowlink := min(v.lowlink, w.index) end if // 若v是根则出栈,并得到一个强连通分量 if (v.lowlink = v.index) then start a new strongly connected component repeat w = S.pop() add w to current strongly connected component until (w = v) output the current strongly connected component end if end function
變數index是深度優先搜尋的節點計數器。 S是堆疊,初始為空,用於儲存已經訪問但未被判定屬於任一強連通分量的節點。注意這並非一個一般深度優先搜尋的堆疊,節點不是在以它為根的子樹搜尋完成後出堆疊,而是在整個強連通分量被找到時。
最外層循環用於尋找未訪問的節點,以保證所有節點最終都會被訪問。 strongconnect進行一次深度優先搜尋,並找到節點v的後繼節點構成的子圖中所有的強連通分量。
當一個節點完成遞迴時,若它的lowlink仍等於index,那麼它就是強連通分量的根。演算法將在此節點之後入堆疊(包含此節點)且仍在堆疊中的節點出堆疊,並作為一個強連通分量輸出。
備註
參考
- ^ Tarjan, RE, Depth-first search and linear graph algorithms, SIAM Journal on Computing, 1972, 1 (2): 146–160, doi:10.1137/0201010
- ^ Harrison, Paul. Robust topological sorting and Tarjan's algorithm in Python. [2011-02-09]. (原始內容存檔於2011-02-15).