tarjan演算法大意

2022-02-06 08:27:42 字數 3450 閱讀 6366

tarjan演算法 (以發現者robert tarjan命名)是乙個在圖中尋找強連通分量的演算法。演算法的基本思想為:任選一結點開始進行深度優先搜尋dfs(若深度優先搜尋結束後仍有未訪問的結點,則再從中任選一點再次進行)。搜尋過程中已訪問的結點不再訪問。搜尋樹的若干子樹構成了圖的強連通分量。

應用到咱們要解決的lca問題上,則是:對於新搜尋到的乙個結點u,先建立由u構成的集合,再對u的每顆子樹進行搜尋,每搜尋完一棵子樹,這時候子樹中所有的結點的最近公共祖先就是u了

引用此文的乙個例子,如下圖(不同顏色的結點相當於不同的集合):

假設遍歷完10的孩子,要處理關於10的請求了,取根節點到當前正在遍歷的節點的路徑為關鍵路徑,即1-3-8-10,集合的祖先便是關鍵路徑上距離集合最近的點。

比如:得出的結論便是:lca(u,v)便是根至u的路徑上到節點v最近的點。

2.2、tarjan演算法如何而來

但關鍵是 tarjan演算法是怎麼想出來的呢?再給定下圖,你是否能看出來:分別從結點1的左右子樹當中,任取乙個結點,設為u、v,這兩個任意結點u、v的最近公共祖先都為1。

於此,我們可以得知:若兩個結點u、v分別分布於某節點t 的左右子樹,那麼此節點 t即為u和v的最近公共祖先。更進一步,考慮到乙個節點自己就是lca的情況,得知:

這個定理就是tarjan演算法的基礎。

一如上文1.1節我們得到的結論:如果當前結點t 滿足 u 而對於本節開頭我們所說的如果要求多個任意兩個結點的最近公共祖先,則相當於是批量查詢,即在很多組的詢問的情況下,或許可以先確定乙個lca。例如是根節點1,然後再去檢查所有詢問,看是否滿足剛才的定理,不滿足就忽視,滿足就賦值,全部弄完,再去假設2號節點是lca,再去訪問一遍。

可此方法需要判斷乙個結點是在左子樹、還是右子樹,或是都不在,都只能遍歷一棵樹,而多次遍歷的代價實在是太大了,所以我們需要找到更好的方法。這就引出了下面要闡述的tarjan演算法,即每個結點只遍歷一次,怎麼做到的呢,請看下文講解。

2.3、tarjan演算法流程

tarjan演算法流程為:

procedure dfs(u);

begin

設定u號節點的祖先為u

若u的左子樹不為空,dfs(u - 左子樹);

若u的右子樹不為空,dfs(u - 右子樹);

訪問每一條與u相關的詢問u、v

-若v已經被訪問過,則輸出v當前的祖先t(t即u,v的lca)

標記u為已經訪問,將所有u的孩子包括u本身的祖先改為u的父親

end普通的dfs 不能直接解決lca問題,故tarjan演算法的原理是dfs + 並查集,它每次把兩個結點對的最近公共祖先的查詢儲存起來,然後dfs 更新一次。如此,利用並查集優越的時空複雜度,此演算法的時間複雜度可以縮小至o(n+q),其中,n為資料規模,q為詢問個數。

2.4、tarjan演算法的應用舉例

引用此文中的乙個例子。

i) 訪問1的左子樹

step 1:從根結點1開始,開始訪問結點1、2、3

節點祖先

step 2:2的左子樹結點3訪問完畢

節點祖先

step 3:開始訪問2的右子樹中的結點4、5、6

節點祖先

step 4:4的左子樹中的結點5訪問完畢

節點祖先

step 5:開始訪問4的右子樹的結點6

節點祖先

step 6:結點4的左、右子樹均訪問完畢,故4、5、6中任意兩個結點的lca均為4

節點祖先

step 7:2的左子樹、右子樹均訪問完畢,故2、3、4、5、6任意兩個結點的lca均為2

節點祖先

如上所述:進行到此step7,當訪問完結點2的左子樹(3),和右子樹(4、5、6)後,結點2、3、4、5、6這5個結點中,任意兩個結點的最近公共祖先均為2。

ii) 訪問1的右子樹

step 8:1的左子樹訪問完畢,開始訪問1的右子樹

節點祖先

step 9:開始訪問1的右子樹中的結點7、8

節點祖先

step 10

節點祖先

step 11

節點祖先

step 12:1的右子樹中的結點7、8訪問完畢

節點祖先

當進行到此step12,訪問完1的左子樹(2、3、4、5、6),和右子樹(7、8)後,結點2、3、4、5、6、7、8這7個結點中任意兩個結點的最近公共祖先均為1。

step 13:1的左子樹、右子樹均訪問完畢

節點祖先

通過上述例子,我們能看到,使用此tarjan演算法能解決咱們的lca問題。

tarjan演算法詳解

參考 tarjan演算法在強連通分量分離中運用很廣,書寫簡單,並且可以拓展到圖的割點,割邊上,十分強大 具體思路 令dfn u 表示當前點的時間戳 low u 表示當前點所能到達的點的時間戳中最小的乙個 到達點u時,將其入棧 拓展點u後代 當且僅當dfn u low u 時,棧頂元素全部出棧,此時出...

Tarjan 演算法筆記

tarjan演算法 tarjan演算法屬於圖論中的乙個演算法,主要用來求乙個圖中的強連通分量,之後就可以做很多事,比如說縮點 求雙聯通分支等。強連通 在乙個有向圖中,對於幾個點,如果它們能夠互相到達,那麼稱它們強連通。強連通分量 可以這樣理解 把乙個圖里的點分成幾坨,每坨中的點都能夠互相到達 他們強...

Tarjan演算法詳解

tarjan演算法的用途 1.求橋和割點 2.求點和邊的雙連通分量 3.求強連通 targan演算法的流程 利用dfs來遍歷圖來構建一種數型的結構 tarjan演算法的兩個核心陣列 1 對於第一種用途 tarjan演算法原理 我們從1開始遍歷,發現6,5,4的low不小於dfn 3 故3為割點 即4...