1。定義:有向圖強連通分量:在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通(strongly connected)。如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量(strongly connected components)。
現在來說說求有向圖強連通分支的tarjan演算法:
演算法思路:
這個演算法思路不難理解,由開篇第一句話可知,任何乙個強連通分量,必定是對原圖的深度優先搜尋樹的子樹。那麼其實,我們只要確定每個強連通分量的子樹的根,然後根據這些根從樹的最低層開始,乙個乙個的拿出強連通分量即可。那麼剩下的問題就只剩下如何確定強連通分量的根和如何從最低層開始拿出強連通分量了。
那麼如何確定強連通分量的根,在這裡我們維護兩個陣列,乙個是indx[1..n],乙個是mlik[1..n],其中indx[i]表示頂點i開始訪問時間,mlik[i]為與頂點i鄰接的頂點未刪除頂點j的mlik[j]和mlik[i]的最小值(mlik[i]初始化為indx[i])。這樣,在一次深搜的回溯過程中,如果發現mlik[i]==indx[i]那麼,當前頂點就是乙個強連通分量的根,為什麼呢?因為如果它不是強連通分量的根,那麼它一定是屬於另乙個強連通分量,而且它的根是當前頂點的祖宗,那麼存在包含當前頂點的到其祖宗的迴路,可知mlik[i]一定被更改為乙個比indx[i]更小的值。
至於如何拿出強連通分量,這個其實很簡單,如果當前節點為乙個強連通分量的根,那麼它的強連通分量一定是以該根為根節點的(剩下節點)子樹。在深度優先遍歷的時候維護乙個堆疊,每次訪問乙個新節點,就壓入堆疊。現在知道如何拿出了強連通分量了吧?是的,因為當前節點是這個強連通分量中最先被壓人堆疊的,那麼在當前節點以後壓入堆疊的並且仍在堆疊中的節點都屬於這個強連通分量。當然有人會問真的嗎?假設乙個節點在當前節點壓入堆疊以後壓入並且還存在,同時它不屬於該強連通分量,那麼它一定屬於另乙個強連通分量,但當前節點是它的根的祖宗,那麼這個強連通分量應該在此之前已經被拿出。現在沒有疑問了吧,那麼演算法介紹就完了。
如下圖:
其實每一次都是去找「環」,如果找到「環」,那說明環中的節點就是強連通分支中的節點,因此每次都是去找環。
演算法流程如下:
tarjan演算法是基於對圖深度優先搜尋的演算法,每個強連通分量為搜尋樹中的一棵子樹。搜尋時,把當前搜尋樹中未處理的節點加入乙個堆疊,回溯時可以判斷棧頂到棧中的節點是否為乙個強連通分量。
定義dfn(u)為節點u搜尋的次序編號(時間戳),low(u)為u或u的子樹能夠追溯到的最早的棧中節點的次序號。由定義可以得出,
low(u)=min
當dfn(u)=low(u)時,以u為根的搜尋子樹上所有節點是乙個強連通分量。
接下來是對演算法流程的演示。
(1)從節點1開始dfs,把遍歷到的節點加入棧中。搜尋到節點u=6時,dfn[6]=low[6],找到了乙個強連通分量。退棧到u=v為止,為乙個強連通分量。
(2)
返回節點5,發現dfn[5]=low[5],退棧後為乙個強連通分量。
(3)(4)繼續回到節點1,最後訪問節點2。訪問邊(2,4),4還在棧中,所以low[2]=dfn[4]=5。返回1後,發現dfn[1]=low[1],把棧中節點全部取出,組成乙個連通分量。
此,演算法結束。經過該演算法,求出了圖中全部的三個強連通分量,,。
可以發現,執行tarjan演算法的過程中,每個頂點都被訪問了一次,且只進出了一次堆疊,每條邊也只被訪問了一次,所以該演算法的時間複雜度為o(n+m)。
求有向圖的強連通分量還有乙個強有力的演算法,為kosaraju演算法。kosaraju是基於對有向圖及其逆圖兩次dfs的方法,其時間複雜度也是o(n+m)。與trajan演算法相比,kosaraju演算法可能會稍微更直觀一些。但是tarjan只用對原圖進行一次dfs,不用建立逆圖,更簡潔。在實際的測試中,tarjan演算法的執行效率也比kosaraju演算法高30%左右。此外,該tarjan演算法與求無向圖的雙連通分量(割點、橋)的tarjan演算法也有著很深的聯絡。學習該tarjan演算法,也有助於深入理解求雙連通分量的tarjan演算法,兩者可以模擬、組合理解。
求有向圖的強連通分量的tarjan演算法是以其發明者robert tarjan命名的。robert tarjan還發明了求雙連通分量的tarjan演算法,以及求最近公共祖先的離線tarjan演算法,在此對tarjan表示崇高的敬意。
演算法**如下:
tarjan演算法求強連通分支
近期做資料結構課程設計,遇到了有向圖的強連通分支的問題,網上採用的是基於深度優先遍歷的tarjan演算法,在考了許多部落格後,還是有些迷,在思考了一番後,終於明白了,所以寫了這篇文章。首先,明確以下幾點。tarjan演算法基於深度優先遍歷。使用時,會用到兩個棧。乙個棧用於dfs,如果是遞迴的tarj...
有向強連通分支Tarjan演算法
本文 自 說到以tarjan命名的演算法,我們經常提到的有3個,其中就包括本文所介紹的求強連通分量的tarjan演算法。而提出此演算法的普林斯頓大學的robert e tarjan教授也是1986年的圖靈獎獲得者 具體原因請看本博 歷屆圖靈獎得主 一文 首先明確幾個概念。強連通圖。在乙個強連通圖中,...
邊雙連通分支
求邊雙連通分支 跑一遍求割點與橋的tarjan得到該圖的割點和橋,去掉橋,其餘連通分支就是邊連通分支了,邊連通分支數是橋數 1。邊連通分支就是去掉最少兩條邊才能將該圖劃分為兩個部分的圖,橋就是乙個圖被去掉一條邊就能變成兩個子圖的那一條邊,構造邊雙連通分支 把雙連通子圖收縮為乙個點,形成乙個樹,需要加...