Tarjan演算法分解強連通分量(附詳細參考文章)

2021-09-27 17:29:06 字數 1353 閱讀 8160

演算法通過dfs遍歷整個連通分量,並在遍歷過程中給每個點打上兩個記號:乙個是時間戳,即首次訪問到節點i的時刻,另乙個是節點u的某乙個祖先被訪問的最早時刻。

時間戳用dfn陣列儲存,最早祖先用low陣列來存,每次dfs遍歷到乙個節點u,即讓這兩個記號等於當前時刻,在後面回溯或者判斷的過程中在來更新low,dnf是一定的,因為第一次訪問時刻一定。然後遍歷u的子節點,也就是跟u相連的點v,依次看子節點的時間戳有沒有打上,也就是看他有沒有被訪問過。\(1\).沒有就繼續dfs點v,在後來回溯的時候,如果v的low比u的low小,也就是v的某一祖先比u還早被訪問,因為u和v是直接相連的,說明u的low也該更小,便更新u的low值。\(2\).如果有,就看這個點有沒有在棧裡,在的話就看v被訪問的時刻是不是比u的low還早,如果是,更新u的low值。

當遍歷完當前節點及其子節點後,檢查u的low與dfn是否相等,如果相等,說明已經找到了乙個強連通區域,就是現在棧中u及**棧的節點。挨個pop出來即可處理。

當這乙個tarjan執行完了後不能立馬退出,因為圖本身有可能是不連通的。還要在迴圈裡tarjan多次。

#include #include #define max_n 1005

using namespace std;

int dfn[max_n];//記錄dfs訪問次序

int low[max_n];//記錄節點最早可追溯到的祖先

int cnt = 0;//時間戳

int stack[max_n];//模擬棧

int top = -1;//棧頂

int flag[max_n];//記錄節點是否入棧

int number = 0;//強連通分量的個數

int j;//棧彈出節點

int g[max_n][max_n];//圖的鄰接矩陣

int n;//圖的節點數目

void tarjan(int u)

e[max_n<<1];

void add(int u,int v)

//讀入資料

void readdata()

}void tarjan(int u)

else if(instack[v])//如果被訪問過且在棧中

}if(low[u]==dfn[u])//找到乙個聯通分量

while(u!=v);

}}//結果處理

void solve()

}for(int i = 1;i<=n;i++)

cout << bcnt << "個強連通分量" << endl;

for(int i = 1;i<=bcnt;i++)

}cout << endl;

}}int main()

強連通分量Tarjan演算法

o v e 通常的tarjan寫法是有個dfn陣列跟乙個instack陣列,我精簡了下 把這兩個陣列都刪去了,用更簡便的寫法代替,也省了空間。int low maxn 記錄這棵樹能到達的最早祖先 其實不一定是最早,但不影響使用 int time 時間戳 int num 連通分量的個數 int bel...

強連通分量 tarjan演算法

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

強連通分量 Tarjan演算法

有向圖強連通分量 在有向圖g中,如果兩個頂點vi,vj間 vi vj 有一條從vi到vj的有向路徑,同時還有一條從vj到vi的有向路徑,則稱兩個頂點強連通。如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。有向圖的極大強連通子圖,稱為強連通分量。tarjan 演算法是基於對圖優先搜素的演算法 每...