無向圖的雙連通分量
1. 概念
設G=(V,E)是連通的無向圖,如果V中頂點a是一個關節點,若V中有頂點v,w使得v,w,a各不相同且v和w之間的每條路都包含a。換言之,如果刪除a和與之相鄰的所有邊時,就會把圖的一個連通分量拆分成多個連通分量。
而若對V中每個不同的三元組v,w,a,在v和w之間都存在一條不包含a的路徑,則說G是雙連通的。因此,僅當一個連通的無向圖沒有關節點時,它才是雙連通的。
邊e1和e2等價,若e1=e2或者有一條環路既包含e1又包含e2則稱邊e1和e2是等價的。
假設Vi是Ei中各邊都彼此連接的頂點集(或者利用邊的等價性來划分等價類),則每個圖Gi=(Vi,Ei)叫做G的一個雙連通分量。
- 雙連通分量是雙連通的
- 對所有的i,j(不相等),Vi和Vj最多一起包含一個頂點
- 當且僅當v是Vi和Vj共同包含的頂點時,v是G的一個關節點

2. 求關節點
假設對連通無向圖G進行深度優先搜索和深度優先編號,產生深度優先生成樹S=(V,T)和回退邊B。
性質:如果一個頂點v的真子孫的所有回退邊都指向v或者比v更深層次(離樹根更遠)的頂點,則v是關節點。若有的回退邊指向v的真祖先,則v不是關節點。
算法步驟:
- 對圖進行深度優先搜索,計算每個頂點v的深度優先編號dfn[v],形成深度優先生成樹
- 計算所有頂點v的low[v]編號是在深度優先生成樹上按后根遍歷順序進行的。low[v]取下述三值的最小者:
- dfn[v]
- dfn[w]:存在回退邊(v,w)的任何頂點w
- low[y]:y是v的任意兒子
- 計算完low編號后,求關節點,根據性質,可知:
- 樹根只要有2個或更多的兒子,它就是關節點,顯然
- 非樹根頂點v是關節點,當且僅當v有某個兒子y,使low[y] >= dfn[v],這里其實就是說其真子孫的回退邊都指向v或者比v更深層次的頂點
代碼如下:
Biconnected_Component(G)
{
T = empty;
count = 1;
for(all in V)
mark v "new"
SerachB(v0); //建立以v0為根的深度優先搜索生成樹
}
SearchB(v)
{
mark v "old";
dfn[v] = count;
count ++;
low[v] = dfn[v];
for(each w in L[v]) {
if(w is marked "new") {
add (v,w) to T;
father[w] = v;
SearchB(w);
if(low[w] > dfn[v])
A biconnected component has been found
low[v] = min(low[v],low[w]);
} else if(w is not father[v])
low[v] = min(low[v],low[w]);
}
}
有向圖的強連通分量
有向圖的一個強連通分量是該圖中頂點的一個最大子集:其中的任意兩個頂點x和y,存在x到y的路徑,也存在y到x的路徑。
令G=(V,E)是一個有向圖,將V分割成若干等價類Vi(l<=i<=r),使得Vi中的v和w等價的充要條件是有一條路徑從v到w,也存在一條路徑從w到v。令Ei(l<=i<=r)是頭、尾均在Vi的邊集,則Gi=(Vi,Ei)是G的強連通分量,簡稱強分量。把只具有一個強分量的有向圖稱為強連通圖。
連接兩個強分量的邊叫做分支橫邊。通過構造G的歸約圖 ,可以展示各強分量間的聯系。歸約圖中每個強分量用一個頂點表示,顯然,歸約圖中不存在環路。

Kosaraju算法步驟:
- 對有向圖G進行深度優先搜索並且對頂點進行
逆編號(即記錄它們的離開時間) - 將G中的每條邊取反方向,構造一個新有向圖Gr
- 根據前面的編號,從編號最大的頂點開始對G,進行一次深度優先搜索,凡是能到達的所有頂點,都形成一棵深度優先搜索樹;若本次搜索沒有到達所有頂點,從圖中刪除這些頂點及相連的邊,繼續重復該動作
- 在Gr的深度優先森林中,每棵樹對應G的一個強連通分量


