tarjan演算法原理介紹

2021-07-03 04:37:41 字數 1714 閱讀 9376

證明比較繁瑣,仔細檢查了應該沒有大錯,記錄一下證明過程。

在有向圖中,強連通分量的定義是:有向圖的某個子圖,其中任意兩個點之間可以互達。

定理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 時,棧頂元素全部出棧,此時出...