1. 程式人生 > >LCA-ST演算法&Tarjan_LCA

LCA-ST演算法&Tarjan_LCA

定義

樹中兩個節點x,y的最近公共祖先(Lowest Common Ancestors,簡稱LCA)指的是既是x祖先,又是y祖先且距離x和y最近的節點。

ST演算法(線上)

我們有一個求x和y的LCA的初始想法:就是先讓x和y中dep較大的節點與dep較小的節點處在同一深度,然後同時向上走,直到相遇,此時相遇的節點即為LCA:
這裡寫圖片描述
複雜度為O(nQ),並不是很好,我們需要優化。
初始想法很明顯的一個缺陷是:每次只走一層,太慢了,而這和RMQ初始想法的缺陷是一樣的。所以我們會想到ST演算法!記錄fa[i][j]表示i向上走2^j次到達的節點(我們認為根向上走若干次會到達自己),那麼很容易得到轉移:
fa[i][j]=fa[fa[i][j-1]][j-1]


ps:我們還可以類似的記錄其他資訊,比如MAX[i][j]表示i向上走2^j次經過的邊(點)權的最大值,從而求出一條路徑中邊(點)權的最大值。

構造好fa之後,如何求x到y的LCA呢?如下(不妨設dep[x]>dep[y]):
1.從大到小列舉i(log2(dep[x]dep[y])~0),如果dep[fa[x][i]]>=dep[y],那麼令x=fa[x][i]。由於這樣可以視為列舉二進位制位,所以處理完畢之後必定有dep[x]=dep[y]。
2.如果x=y,則x(y)即為LCA,結束。
3.從大到小列舉i(log2dep[x]~0),如果fa[x][i]!=fa[y][i],那麼令x=fa[x][i],y=fa[y][i]。處理完畢之後x(y)再向上走一次必定就是LCA,原理同1。
4.令x=fa[x][0],此時的x即為LCA。
複雜度為O

((n+Q)log2n)

Tarjan_LCA(離線)

求LCA還有個離線演算法Tarjan,Tarjan的想法是先把所有詢問存下來,然後一次性全部處理,所以是離線的。過程如下:
1.用DFS遍歷這棵樹(優先處理出子樹)。
2.假設目前遍歷的點是x,子樹son已經處理完畢,那麼將x與son用並查集合並。
3.列舉與x有關的詢問(x,y),如果y已經訪問過,那麼LCA(x,y)=getfa(y)即y目前的祖先。

這裡簡要說明一下為什麼LCA(x,y)=getfa(y):
這裡寫圖片描述
由於y已經訪問過,根據深度優先搜尋DFS的性質,一定有dep[y]>=dep[x]。
因為y在x之前被訪問,所以y必定已經和LCA處於同一個連通塊中。而且x還沒處理完畢,意味著LCA也沒處理完畢,所以LCA必定是這個連通塊的祖先。

還有一個小問題,就是我們怎麼保證y已經訪問過了呢?如果沒有訪問過,不是無法處理出LCA了?所以我們對於一個詢問(x,y),還需要新增詢問(y,x),這樣就可以方便的解決這個問題了。

由於並查集路徑壓縮之後可以視為常數,所以複雜度為O(n+Q)

模板題

相關推薦

LCA-ST演算法&Tarjan_LCA

定義 樹中兩個節點x,y的最近公共祖先(Lowest Common Ancestors,簡稱LCA)指的是既是x祖先,又是y祖先且距離x和y最近的節點。 ST演算法(線上) 我們有一個求x和y的LCA的初始想法:就是先讓x和y中dep較大的節點與dep

LCA線上演算法-基於ST

LCA演算法-ST線上演算法 轉自: https://blog.csdn.net/qq_35935435/article/details/54916022 這篇文章講LCA演算法(Least Common Ancestor)。 LCA:顧名思義,指在一棵有根樹中,距離兩個結點u和v最近的

LCA 線上演算法 dfs + ST演算法 總結 hihocoder 1069

連結:http://hihocoder.com/problemset/problem/1069 思想: 利用dfs + ST 演算法 記錄下dfs的序列,還有dfs過程中每一個點的深度,對應到之前的dfs的序列中。還需要記錄一個在dfs中每一個節點首次出現

HDU - 2586 How far away? 在線LCA ST算法

ole poi cto st算法 求解 style after nsis return There are n houses in the village and some bidirectional roads connecting them. Every day peo

LCA(ST)詳解 Codeforces932D-倍增+二分搜索

com code 倍增 ima 技術 詳解 idt for img 占坑,明天要是還沒寫就不睡了(▼ヘ▼#) LCA(ST)詳解 Codeforces932D-倍增+二分搜索

資料結構:線段樹及ST演算法比較

ST演算法是一種高效的計算區間最值的方法。 他的思想是將詢問區間分解成兩個最長的二次冪的長度的區間並集的形式。 所以與線段樹不同,這種區間分解其實存在相交的分解。 因此ST演算法能維護的只是一些簡單的資訊,比如區間最值或者區間gcd問題 ST演算法的優勢: 實現簡單(qwq為什麼我覺得線段樹更

hihocoder1068 RMQ-ST演算法

思路: 這是ST表模板。遇到一道indeed筆試題需要用這個演算法,順便學習一下。那道題是說給定一個一維陣列和一些查詢[Li, Ri],要求計算[Li, Ri]區間內子段和的絕對值的最大值。解法是使用ST表計算所求區間內最大字首和 - 最小字首和即可。 實現: 1 #include <bi

SPOJ RPLN (模板題)(ST演算法)【RMQ】

<題目連結> 題目大意:給你一段序列,進行q次區間查詢,每次都輸出詢問區間內的最小值。 解題分析: RMQ模板題,下面用線上演算法——ST演算法求解。不懂ST演算法的可以看這篇部落格  >>> 1 #include <cstdio> 2 #

hihoCoder week17 最近公共祖先·三 lca st

col cin mes map ons ini include name pan 記錄dfs序列,dfn[tot] 記錄第tot次訪問的節點 然後查兩點在dfs序中出現的第一次 id[u] id[v] 然後 找 dep[k] = min( dep[i] ) {i 屬於

hihoCoder week17 最近公共祖先·三 lca st

記錄dfs序列,dfn[tot] 記錄第tot次訪問的節點 然後查兩點在dfs序中出現的第一次 id[u] id[v] 然後  找 dep[k] = min( dep[i] ) {i 屬於 [id[u], id[v]]} 最後dfn[k] 就是所求.. 感覺弄來弄去 就是 在對映... 無非

最近公共祖先·三 (LCA線上演算法

描述 上上回說到,小Hi和小Ho使用了Tarjan演算法來優化了他們的“最近公共祖先”網站,但是很快這樣一個離線演算法就出現了問題:如果只有一個人提出了詢問,那麼小Hi和小Ho很難決定到底是針對這個詢問就直接進行計算還是等待一定數量的詢問一起計算。畢竟無論是一個詢問還是很多個詢問,使用離線演算法

[HDU2586] How far away ?{LCA.tarjan演算法/倍增演算法}

文章目錄 題目 解題思路 程式碼`倍增(TLE)` 程式碼`tarjan演算法(AC)` $tanjan$演算法本質上是使用並查集對“向上標記法”的優化 題目 http://acm.hdu.edu.cn

ST演算法求最值:

const int maxn=50005; int a[maxn],dp[maxn][30],d[maxn][30]; void rmq(){ for(int i=1;i<=n;i++){dp[i][0]=a[i];d[i][0]=a[i];} for(

LCA離線演算法-Tarjan演算法

Tarjan演算法的關鍵就在於ancestor陣列。該陣列用來儲存每個節點的祖先。注意,我們在tarjan演算法中用到了並查集,但是並查集中每個集合的最終father並不是所謂的祖先,兩個不是同一個東西!並查集中的father是一個葉子節點,為什麼這麼做呢?因為我們在更新中間節點的祖先時,採用anc

二維RMQ-------ST演算法

Poj 2019 Cornfields【二維RMQ-------ST演算法】 2016年08月03日 13:11:18 mengxiang000000 閱讀數:962 標籤: Poj 2019Pku 2019更多 個人分類: dp 版權宣

loj10121 與眾不同(ST演算法)(二分)

題目 A 是某公司的 CEO,每個月都會有員工把公司的盈利資料送給 A,A 是個與眾不同的怪人,A 不注重盈利還是虧本,而是喜歡研究「完美序列」:一段連續的序列滿足序列中的數互不相同。 A 想知道區間

ST演算法詳解+例題 O(1)查詢區間最大最小值

RMQ問題 RMQ (Range Minimum/Maximum Query)問題是指:對於長度為n的數列A,回答若干詢問RMQ(A,i,j)(i,j<=n),返回數列A中下標在i,j裡的最小(大)值,也就是說,RMQ問題是指求區間最值的問題。

【模板】LCA Tarjan演算法 (模板題:洛谷P3379)

題目描述 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。 輸入輸出格式 輸入格式: 第一行包含三個正整數N、M、S,分別表示樹的結點個數、詢問的個數和樹根結點的序號。 接下來N-1行每行包含兩個正整數x、y,表示x結點和y結點之間有一條直接連線的邊

lca倍增演算法模板

1431: LCA 最近公共祖先 時間限制: 1 Sec  記憶體限制: 128 MB提交: 244  解決: 36 [提交][狀態] 題目描述 給一棵樹, 節點數為N(1 <= N &

lca倍增演算法學習記錄

找最近公共父節點這問題很容易想到讓兩節點一起往上走最後相遇,但這樣的dfs顯然很慢,於是就需要倍增。就是用二進位制的思維,以1,2,4,8等2的階層步長接近答案,比一步一步向上要快很多。 所以要dfs出來點的2^k的父親節點與該節點的深度。 找lca時先將下