證明比較繁瑣,仔細檢查了應該沒有大錯,記錄一下證明過程。
在有向圖中,強連通分量的定義是:有向圖的某個子圖,其中任意兩個點之間可以互達。
定理1:乙個完整的強連通分量一定包含在一棵深度優先搜尋樹中。
定理2:子圖是強連通分量<=>子圖中的每一條路徑都歸屬於乙個環狀(除非只有乙個點)。
證明:根據強連通分量的定義,任意兩個點之間可以互達,所以等價於任意兩個點之間的路徑是乙個環的一部分。
假設圖有n
個節點,
m條邊。該演算法可以在o(
n+m)的時間複雜度中輸出所有強連通分量。
tarjan演算法是在深度優先搜尋的基礎上進行的。
首先演算法有3
個資料結構:
dfn[n] 儲存每乙個節點訪問過程中的時間戳
time_stamp
low[n] 儲存每乙個節點在深度優先搜尋的子孫中
time_stamp
的最小值(搜尋的過程中會由於遇到迴路,訪問到之前訪問過的節點,所以子孫的
time_stamp
可能比該節點小)
stack,存放已經訪問的節點。
tarjan演算法流程:
使用遞迴的方法進行深度優先搜尋
int tarjan( int index ) else if(v沒在
stack
中 &&
沒有訪問過)
} if( dfn[index] == low[index] )
} return low[index];
}
1.為什麼紅字部分出棧的是乙個強連通分支:
根據定理2
,等價於證明,出棧的部分,節點路徑都是某個環的一部分。
已知:目前棧內的將出棧部分,假如節點下標為i
,則一定有
dfn[i]>=low[i]
(當且僅當
i=最後乙個出棧的節點下標時取等號)。
運用反證法:假如有某條路徑不屬於某個環,如下圖中的路徑b->a
,則這段路徑的末端點a的dfn[a] = low[a],
且該點是出棧的某條路徑的末端點,而不是初始點,所以不可能是最後出棧的那個點,和已知矛盾。所以,出棧的任意一條路徑都屬於某個環,即出棧的子圖是乙個強連通分量。
2.為什麼紅字部分出棧的強連通分支是完整的:
假設出棧的部分不完整,則本應該在這次出棧的點可能存在於棧的哪些部分呢?
1.之前出棧的部分
2.還沒有入棧的部分
3.還沒有出棧的部分
首先看2,不可能。因為假如沒有入棧,說明這些點沒有在這棵深度優先搜尋樹中,假如這些點在本該在該強連通分量中,則和定理1相違背,所以情況2中不可能包含本應該出棧的強連通分量中的點。
再看3,也不可能。3中的點的dfn 和 low都分別小於本次出棧的點的dfn和low,也就說明本次出棧的點都無法訪問到還沒有出棧的點,所以情況3中不可能包含本應該出棧的強連通分量中的點。
最後看情況1,其實情況1和情況3是類似的,之前出棧的部分a如果和本次出棧的強連通分量b可以組成更大的強連通分量,這就等價於,以之前出棧的強連通分量a為視角,亦是說a是不完整的,a中缺少的部分在還未出棧的節點和還沒有訪問的節點之中。這和之前的情況2,情況3推導矛盾,所以,情況1也不可能。
所以綜上所述,紅字部分出棧的強連通分支是完整的。
Tarjan演算法介紹
tarjan演算法是圖論中的一種演算法,用作於圖的聯通性 如果沒學過這樣東西的人可以先收藏一下,等學過了在看 targan演算法的流程 利用dfs來遍歷圖來構建一種數型的結構 tarjan演算法的兩個核心陣列 dfn 我們用dfn陣列記錄 low 我們用low i 表示乙個節點的子樹中可以到達最小的...
Tarjan演算法介紹
一種由robert tarjan提出的求解有向圖強連通分量的線性時間的演算法。給定無向圖 g v,e 如果割掉點x,圖中的連通塊數量增加,則稱x為g的割點 如果割掉邊e,圖中的連通塊數量增加,則稱e為g的橋或割邊 在圖的深度優先搜尋中,按照每個節點的訪問順序所給每個點編的號,該編號叫做 時間戳 記為...
tarjan演算法詳解
參考 tarjan演算法在強連通分量分離中運用很廣,書寫簡單,並且可以拓展到圖的割點,割邊上,十分強大 具體思路 令dfn u 表示當前點的時間戳 low u 表示當前點所能到達的點的時間戳中最小的乙個 到達點u時,將其入棧 拓展點u後代 當且僅當dfn u low u 時,棧頂元素全部出棧,此時出...