18.12.30 【sssx】tarjan演算法
阿新 • • 發佈:2018-12-30
資料結構
dfn[i] :編號為i的結點在dfs遍歷圖的過程中的訪問序號(開始時間)
low[i] :從i結點出發dfs過程中i下方的結點能到達的最早的當前搜尋路徑上的結點的開始時間。(初始時 low[i]=dfn[i] )
操作
- 遍歷結點沒被訪問過的就開始dfs,碰到哪個結點哪個結點就入棧,棧中結點只有在其所屬的強連通分量已經全部求出時才會出棧。
- 連線結點u的當前搜尋路徑上的v, low[u]=min(low[u],dfn[v]) ,如果low[u]被更新為 dfn[v] 則表明目前u可達的最早結點時v
- 對於u的子結點v,當由它出發的dfs結束回到u時, low[u]=min(low[u],low[v]) 。
- 一個結點完成dfs後, low[u]=dfn[u] 說明u是一個強連通分量在dfs搜尋樹中的根。
- 將棧中結點一直彈出直到u,彈出的結點時一個強連通分量
1 void Tarjan(u) { 2 dfn[u]=low[u]= ++index //index是開始時間 3 stack.push(u) 4 for each (u, v) in E { // E是邊集合 5 if (v isnot visited) { 6 tarjan(v) 7 low[u] = min(low[u], low[v]) 8 } 9 else if (v in 當前搜尋路徑) {//當前搜尋路徑就是起點(根)到u的路徑 10 low[u] = min(low[u], dfn[v]) 11 } 12 } 13 if (dfn[u] == low[u]) { //u是一個強連通分量的根 14 repeat 15 v = stack.pop16 print v 17 until (u== v) 18 } //退棧,把整個強連通分量都彈出來 19 } //複雜度是O(E+V)的
一些圖論定理
有向無環圖中,唯一出度為0的點=可以由任何點出發均可達的點
有向無環圖中所有入度不為0的點一定可以由某個入度為0的點出發可達。