LCA學習筆記

2021-09-13 14:47:14 字數 2138 閱讀 2674

在有根樹中(包括二叉樹和其他各種樹),兩個節點ta , tb的共同祖先中和兩個節點最近的那個被稱為最近共同祖先(lca,lowest common ancestor)

比如上面這張圖中

2和8的lca是1

7和5的lca是5

5和6的lca是3

先從最簡單的想法出發去找兩個點(w和u)的lca,也就是一步一步向上尋找,先把深度大的那個節點往上拉,直到兩個節點的深度相同,然後兩個點同時向上查詢,直到第一次兩個節點相遇為止,那個點就是w和u的lca。查詢的時間複雜度為o(n),實際上差不多是o( depth(w)+depth(u) ),

比如上圖中的2和8號節點,因為8號節點深度更深,所以先把它拉到和2號節點一樣深度的位置,也就是3號節點,再同時向上搜,就能找到1是lca。

對此我們要知道各個節點的深度,和它所對應的父節點,所以初始化建立兩個陣列記錄,用dfs搜尋一遍,把資料記錄下來就行了。根節點的父節點就設為-1,深度為0。

**很簡單:

vector<

int> mp[maxn]

;//記錄各個點相連的其他點

int parent[maxn]

;//記錄各個點的父節點

int depth[maxn]

;//記錄各個點的深度

void

dfs(

int id,

int p,

int deep)

void

init()

接下來就是查詢lca,普通的查詢也很簡單,直接看**就好了

int

lca(

int ta,

int tb)

return ta;

}

如果查詢次數不是很多的話用上面的普通演算法還是可以的,當時當查詢次數變多了之後,每次都用o( n )來查值就會很慢,有沒有什麼辦法可以快速查詢lca的值呢?顯然是有的。

我們可以發現,當w和u的lca找到之後,再向上查詢,(因為w和u已經匯聚到了乙個節點上了),所以繼續向上查詢查到的也都是相同的值,這樣我們可以利用二分的思想來找到第乙個相同的值,具體如下:

當知道乙個點的父節點之後,也就是深度少了20的父節點,我們用它來找到深度減少21的祖先節點,也就是parent2[ x ] = parent[ parent[ x ] ] 。同樣的,我們可以找的深度減少22的祖先節點,parent4[ x ] = parent2[ parent2[ x ] ]。這樣遞推下去就可以得到一張用於查詢的表(如果祖先節點不存在就表示為-1)。之後查詢的時候利用這張表來進行二分搜尋就可以將查詢的時間複雜度降低到o(logn),是乙個很大的進步。

具體操作就是比樸素的演算法稍微複雜了一點,初始化的時候要把所有倍增的節點也計算出來。

具體初始化:

vector<

int> mp[maxn]

;//記錄連線點

int parent[maxn][30

];//第二維只要》log2(maxn)就好了

//parent[i][j]表示編號為i的節點比他深度小了2^j的點的編號

int depth[maxn]

;//記錄各個點的深度

int maxx =-1

;//下面可以用來優化,用來記錄最大的深度

void

dfs(

int id,

int p,

int deep)

void

init()

}}

初始化的時候就是會比原來多乙個步驟,複雜度變成o(n logn)

接下來就是查詢的操作了,單次查詢o(log n)

int

lca(

int ta,

int tb)

}return parent[ta][0

];//這時parent[ta][0]和parent[tb][0]就是lca(ta,tb)

}

洛谷的模板題:

LCA學習筆記

寫在前面目錄 一 lca的定義 二 暴力法求lca 三 倍增法求lca 四 樹鏈剖分求lca 五 lca典型例題 題目完成度 一 lca的定義 lca指的是最近公共祖先。具體地,給定一棵有根樹,若結點z既是結點x的祖先,又是結點y的祖先,則稱z是x,y的公共祖先。在x,y的公共祖先中,深度最大的乙個...

Tarjan 學習筆記 LCA

常用的求 lca 的演算法有 ta rjan df s st 倍增o logn o nlog n 之間。ta rjan 是 離線 演算法。顧名思義,就是在一次遍歷中把所有詢問一次性解決,所以其時間複雜度是 o n q 利用了 df s 和並查集的思想,祖先回溯記錄為上乙個,如果已經某一點遍歷過了就 ...

學習筆記 lca 倍增

求一棵樹上兩個節點的最近公共祖先有兩種演算法 tarjan 離線 這篇博文只介紹倍增的寫法.f i j 表示節點 i 的祖先中,與節點 i 距離為 2 j 的節點編號.那麼 f i j beginroot i root father i j 0,i not root f i j f f i j 1 ...