Book 強連通分量

2022-05-24 15:57:09 字數 896 閱讀 9472

2014-10-14 23:01:26

最近學了一發強連通分量,來小結一下。

一、定義:在乙個有向圖中,如果任意兩個點都是「相互可達」的,那麼說這個圖是強連通的。有向圖的極大強連通子圖,稱為強連通分量(strongly connected components)。易得:強連通圖的強連通分量就它自己。

二、具體求法:

(1)tarjan

這個演算法利用了dfs時間戳。思考:假設我們dfs搜到了乙個scc,那麼從這個點(令為k點)搜下去,總能找到乙個子節點(令為p點),使得p能返回k,那麼從 k -> p 這一段dfs路徑上的點就是處於乙個scc中的。我們發現這個過程是可以遞迴處理的,假設有兩個scc串在一次,那麼dfs下去會先處理掉比較深的(也就是時間戳大的)scc,然後回溯回去處理比較淺的scc。所以要定理low[i]陣列記錄 i 點的子節點能返回的最祖先節點的時間戳,dfn[i]:i 點的時間戳。

1

void dfs(int

p)10

else

if(!sc[v])13}

14if(low[p] ==dfn[p])22}

23}2425

void

tarjan()

(2)縮點

縮點的目的在於把有向圖中的各個強連通分量縮成乙個點,然後有向圖就變成了dag,更利於分析問題,而且方便記憶化搜尋。

具體做法是:tarjan完後重新根據scc建圖,掃一遍原圖中的所有邊,如果該邊對應的兩個點在同乙個scc中,不用建邊;否則,在兩個scc間建一條有向邊。轉化為dag。

(至於有人用並查集來做。。。不太了解)

(3)後言

watashi翻譯的書裡提供的是兩次dfs的做法(需要將邊反向),為kosaraju演算法。總的來說tarjan演算法的效率比kosaraju高30%

強連通分量 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演算法求強連通分量。define n 1000 struct edge e 100000 int ec,p...

強連通分量

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