tarjan演算法基於深度優先搜尋, 每個強連通分量為搜尋樹中的一棵子樹. 搜尋時, 把當前搜尋樹中未處理的結點加入堆疊, 回溯時就可判斷棧頂到棧中的結點是否為乙個強連通分量.
dfn[u]: 記錄結點u在dfs過程中被遍歷到的次序號(時間戳).
對於一棵dfs樹, 對於原圖中的非樹邊, 為便於描述, 定義:
前向邊: 祖先->兒子的邊.
後向邊: 兒子->祖先的邊.
橫叉邊: 沒有祖先兒子關係的邊(注意橫叉邊
只會往dfn減小的方向連線).
low[u]: 記錄結點u或u的子樹能夠追溯到的dfn最小的值(棧中標號的最小點)
由定義, 顯然有:
⚫ 若(u,v)為樹邊, low[u] = min;
⚫ 若(u,v)是指向棧中結點的後向邊, low[u] = dfn(v).
定理: 當dfn[u] = low[u]時, 以u為根的搜尋子樹上所有結點構成乙個強連通分量.
證明: dfn[u]表示u點被dfs到的時間, low[u]表示u和u所有的子樹所能到達的點中dfn最小值.
dfn[u]=low[u], 這說明u點及u的子樹結點最多只有指向u點的邊, 而沒有指向u的祖先的邊了.
顯然, 遍歷過的結點從u出發又最終回到u形成乙個環, 即u點與它的子孫結點構成了強連通分量.
inline void paint(int x)
void tarjan(int u)
else if (ins[v]) //後向邊(排除橫叉邊)
low[u] = min(low[u], dfn[v]);
}if (dfn[u] == low[u])
paint(u);}}
Tarjan演算法模板
tarjan演算法是根據棧和dfs來實現。每個點有2個資料 dfn和low 結點1的dfn為1,low也為1,然後dfs到3,3的dfn為2,low為2,每次訪問乙個就dfn 當訪問的時候時是棧中結點時,就將low變為那個棧中結點的dfn,這樣可以保證low與dfn不相同。如果訪問不到棧中的結點,就...
Tarjan演算法 模板
只是下一下模板,如果還是沒有懂得原理的,可以看一下這位大牛的部落格 include include include include using namespace std const int maxn 1100 struct node edge maxn int head maxn int dfn ...
Tarjan演算法模板
一 tarjan有向圖的強連通 tarjan const int maxn 200100 const int maxm 500100 struct edgeedge maxm int head maxn tot int low maxn dfn maxn stack maxn belong maxn...