近期做資料結構課程設計,遇到了有向圖的強連通分支的問題,網上採用的是基於深度優先遍歷的tarjan演算法,在考了許多部落格後,還是有些迷,在思考了一番後,終於明白了,所以寫了這篇文章。
首先,明確以下幾點。
tarjan演算法基於深度優先遍歷。使用時,會用到兩個棧。乙個棧用於dfs,(如果是遞迴的tarjan演算法,是隱式地使用了系統堆疊);另乙個棧就是要儲存連通分支的資訊了,以下說的棧都是這個棧。
每個頂點有兩個屬性標記,dfn和low。
明確狀態
入棧,開始訪問乙個節點時,dfn == low == 當前是第幾個訪問到的序列號index
出棧,當dfn == low,且該節點沒有出邊時,得到了子樹的根,將其以及之後的(棧中)所有節點出棧,這樣便找到了乙個強連通分支
其他,當dfn != low,且該節點沒有出邊時,不做任何操作,只是回退到上乙個節點,繼續處理
演算法過程
對乙個頂點進行tarjan時,主要是對出邊的檢查
在進行tarjan(i)時,先後進行兩步操作:邊的檢查、low和dfn的檢查
先進行邊的檢查
如果有這樣的邊:i->j,有以下三種情況:
當i的出邊均訪問完後,檢查dfn和low
c++**
#include #include using namespace std;
int g[7][7]; //以鄰接矩陣表示6*6的圖,索引0不用
int index=0;
int dfn[7];
int low[7];
int c=1; //標記連通分支
stacktarjan; //儲存節點的棧
int component[7]; //記錄最終節點所屬的強連通分支
bool isinstack[7]; //是否在棧中
bool visited[7]; //是否訪問過
void init();
int j[8]=;
for(int m=1;m<=6;m++) //初始化鄰接矩陣
for(int n=1;n<=6;n++)
g[m][n]=0;
for(int k=0;k<8;k++) //增加邊
g[i[k]][j[k]]=1;
for(int k=1;k<=6;k++)
}void tarjan(int i)
回退到上乙個頂點5
low(5)=min( low(5) ,low(6))= 3
dfn == low ,出棧得到連通分支
回退到上乙個頂點3
low(3)=min( low(3) ,low(5))= 2
有邊3->4(狀態1),tarjan(4):
有邊4->6(狀態3)
有邊4->1(狀態2):
low(4)=min( low(4) ,dfn(1))= 1
dfn != low
回退到上乙個頂點3
low(3)=min( low(3) ,low(4))= 1
dfn != low
回退到上乙個頂點1
low(1)=min( low(1) ,low(3))= 1
有邊1->2(狀態1),tarjan(2):
有邊2->4(狀態2):
low(2)=min( low(2) ,dfn(4))= 5
dfn != low
回退到上乙個頂點1
low(1)=min( low(1) ,low(2))= 1
dfn == low ,,出棧得到連通分支
上述過程迴圈
有向強連通分支Tarjan演算法
本文 自 說到以tarjan命名的演算法,我們經常提到的有3個,其中就包括本文所介紹的求強連通分量的tarjan演算法。而提出此演算法的普林斯頓大學的robert e tarjan教授也是1986年的圖靈獎獲得者 具體原因請看本博 歷屆圖靈獎得主 一文 首先明確幾個概念。強連通圖。在乙個強連通圖中,...
強連通分支
1。定義 有向圖強連通分量 在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通 strongly connected 如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量 strongly connected components 現在來...
tarjan 演算法 求強連通分量)
全網最詳細tarjan演算法講解,我不敢說別的。反正其他tarjan演算法講解,我看了半天才看懂。我寫的這個,讀完一遍,發現原來tarjan這麼簡單!tarjan演算法,乙個關於 圖的聯通性的神奇演算法。基於dfs 迪法師 演算法,深度優先搜尋一張有向圖。注意!是有向圖。根據樹,堆疊,打標記等種種神...