Tarjan演算法求強連通分量

2021-08-25 12:14:41 字數 1746 閱讀 6261

有向圖強連通分量的tarjan演算法

在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通(strongly connected)。如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量(strongly connected components)。

下圖中,子圖為乙個強連通分量,因為頂點1,2,3,4兩兩可達。,也分別是兩個強連通分量。

直接根據定義,用雙向遍歷取交集的方法求強連通分量,時間複雜度為o(n^2+m)。更好的方法是kosaraju演算法或tarjan演算法,兩者的時間複雜度都是o(n+m)。本文介紹的是tarjan演算法。

tarjan演算法是基於對圖深度優先搜尋的演算法,每個強連通分量為搜尋樹中的一棵子樹。搜尋時,把當前搜尋樹中未處理的節點加入乙個堆疊,回溯時可以判斷棧頂到棧中的節點是否為乙個強連通分量。

定義dfn(u)為節點u搜尋的次序編號(時間戳),low(u)為u或u的子樹能夠追溯到的最早的棧中節點的次序號。由定義可以得出,

? view code cpp

low(u)

=min

當dfn(u)=low(u)時,以u為根的搜尋子樹上所有節點是乙個強連通分量。

演算法偽**如下

view code cpp

tarjan(u)

接下來是對演算法流程的演示。

從節點1開始dfs,把遍歷到的節點加入棧中。搜尋到節點u=6時,dfn[6]=low[6],找到了乙個強連通分量。退棧到u=v為止,為乙個強連通分量。

返回節點5,發現dfn[5]=low[5],退棧後為乙個強連通分量。

繼續回到節點1,最後訪問節點2。訪問邊(2,4),4還在棧中,所以low[2]=4。返回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表示崇高的敬意。

void tarjan(

int i)

else

if(instack[j]

&& dfn[j]

)low[i]

=dfn[j];}

if(dfn[i]

==low[i]

)while

(j!=i);}

}void solve(

)

強連通分量 tarjan求強連通分量

雙dfs方法就是正dfs掃一遍,然後將邊反向dfs掃一遍。挑戰程式設計 上有說明。雙dfs 1 include 2 include 3 include 4 include 5 6using namespace std 7const int maxn 1e4 5 8 vector g maxn 圖的鄰...

tarjan 演算法 求強連通分量)

全網最詳細tarjan演算法講解,我不敢說別的。反正其他tarjan演算法講解,我看了半天才看懂。我寫的這個,讀完一遍,發現原來tarjan這麼簡單!tarjan演算法,乙個關於 圖的聯通性的神奇演算法。基於dfs 迪法師 演算法,深度優先搜尋一張有向圖。注意!是有向圖。根據樹,堆疊,打標記等種種神...

Tarjan演算法求強連通分量

有向圖強連通分量的tarjan演算法 在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通 strongly connected 如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量 strongly connected component...