**自
一.演算法簡介
我們定義:
如果兩個頂點可以相互通達,則稱兩個頂點強連通(strongly connected)。如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。有向圖的極大強連通子圖,稱為強連通分量(strongly connected components)。
例如:在上圖中, , , 三個區域可以相互連通,稱為這個圖的強連通分量。
tarjan演算法是基於對圖深度優先搜尋的演算法,每個強連通分量為搜尋樹中的一棵子樹。搜尋時,把當前搜尋樹中未處理的節點加入乙個堆疊,回溯時可以判斷棧頂到棧中的節點是否為乙個強連通分量。
再tarjan演算法中,有如下定義。
dfn[ i ] : 在dfs中該節點被搜尋的次序(時間戳)
low[ i ] : 為i或i的子樹能夠追溯到的最早的棧中節點的次序號
當dfn[ i ]==low[ i ]時,為i或i的子樹可以構成乙個強連通分量。
二.演算法圖示
以1為tarjan 演算法的起始點,如圖
順次dfs搜到節點6
回溯時發現low[ 5 ]==dfn[ 5 ] , low[ 6 ]==dfn[ 6 ] ,則 , 為兩個強連通分量。回溯至3節點,拓展節點4.
拓展節點1 , 發現1再棧中更新low[ 4 ],low[ 3 ] 的值為1
回溯節點1,拓展節點2
自此,tarjan algorithm 結束, , , 為圖中的三個強連通分量。
不難發現,tarjan algorithm 的時間複雜度為o(e+v).
#include#includeusing
namespace
std;
#define maxn 1005
struct
edgeedge[maxn*maxn];
int fi[maxn],se,col[maxn],sc,sta[maxn],top,dfn[maxn],low[maxn],df;//
col為每個點屬於的強連通分量,sta為模擬的棧;
bool
vis[maxn];
inline
void add_edge(int u,int
v)void tarjan(int
x)
if(dfn[x]==low[x])
top--;
}}int
main()
強連通分量 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求強連通分量
強連通分量 有向圖強連通分量 在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通 strongly connected 如果有向圖g的每兩個頂點都強連通,則稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,成為強連通分量 strongly connected components 直...
tarjan求強連通分量
tarjan求強連通分量 我們知道,在有向圖g中,如果任意兩個頂點都是連通的 所謂連通就是兩個頂點都能互相到達 那麼這個圖就是強連通圖。非強連通圖的極大強連通子圖,被稱為強連通分量。那麼什麼是極大強連通子圖呢?舉個例子幫助理解一下 例如下面圖一所示,其中子圖就是乙個極大強連通子圖,子圖也是乙個極大強...