tarjan演算法的基本框架就是dfs,其基本原理是有向圖至少存在一棵深搜子樹,其結點集合構成乙個強連通分量,這是顯然的,因為必定有乙個強連通分量最後被dfs,這個強連通分量的結點構成深搜樹的一棵子樹。
有了以上結論後,求強連通分量就有思路了,我們在每棵子樹深搜完成後判斷這棵子樹是否構成強連通分量即可,關鍵在於如何判斷一棵子樹是否構成強連通分量。
注意到最先搜尋完的子樹是那些葉子結點,要判斷葉子結點是否構成強連通分量很簡單,若存在葉子結點與其祖先結點的連邊,則該葉子結點不構成強連通分量,否則構成強連通分量。tarjan演算法用pre[v]陣列和low[v]陣列來判斷子樹是否構成強連通分量,pre[v]儲存結點v在先序遍歷中的訪問順序,以下統稱深度優先數,low[v]儲存從v出發能到達的所有結點的最小深度優先數,用葉子結點來解釋,v為葉子結點,
當low[v]若深搜樹中存在乙個葉子結點構成強連通分量,則通過以上判斷可以求出,也即求出了第乙個強連通分量;
若深搜樹中所有葉子結點都不構成強連通分量,此時葉子結點必定與其父結點同在乙個強連通分量中,可以將其縮到父結點中(具體操作是更新父結點的low陣列),原來的父結點就變成了「大」葉子結點,還是通過low[v]=?pre[v]來判斷這個「大」葉子結點是否構成強連通分量,一直這樣下去,葉子結點將越來越大,直到求出第乙個強連通分量為止。
在求出第乙個強連通分量後,我們將其包含的結點在原圖中刪除,問題又轉化成了求第乙個強連通分量的問題,理解還是一樣的,以此類推,直到所有的強連通分量均被求出,此時演算法結束。
參考**:
#include
#include
#include
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
#define n 100
int pre[n],low[n],id[n],s[n],t,cnt,top,n,m;
vectorg[n];
//初始化
void init()
//tarjan演算法主體
void dfs(int u)
init();
for(i=0;ifor(i=0;ifor(i=0;iprintf("case %d: ",++kase);
for(i=0;iprintf("} ");
}printf("\n");
}return 0;
}
tarjan 演算法 求強連通分量)
全網最詳細tarjan演算法講解,我不敢說別的。反正其他tarjan演算法講解,我看了半天才看懂。我寫的這個,讀完一遍,發現原來tarjan這麼簡單!tarjan演算法,乙個關於 圖的聯通性的神奇演算法。基於dfs 迪法師 演算法,深度優先搜尋一張有向圖。注意!是有向圖。根據樹,堆疊,打標記等種種神...
Tarjan演算法求強連通分量
有向圖強連通分量的tarjan演算法 在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通 strongly connected 如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量 strongly connected component...
Tarjan演算法求強連通分量
有向圖強連通分量的tarjan演算法 在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通 strongly connected 如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量 strongly connected component...