LCA學習筆記

2022-04-28 20:54:19 字數 3083 閱讀 3051

寫在前面目錄

一、lca的定義

二、暴力法求lca

三、倍增法求lca

四、樹鏈剖分求lca

五、lca典型例題

題目完成度

一、lca的定義

lca指的是最近公共祖先。具體地,給定一棵有根樹,若結點z既是結點x的祖先,又是結點y的祖先,則稱z是x,y的公共祖先。在x,y的公共祖先中,深度最大的乙個結點稱為x,y的最近公共祖先,記為lca(x,y)

go back

、暴力法求lca

暴力法,顧名思義,非常暴力,這裡簡單介紹一下

先dfs一遍找出每個點的深度,然後先從深度大的往上跳,跳到x,y兩個點深度相同。

如果發現此時x和y是同乙個結點,那麼原本深度小的那個結點就是兩個點的最近公共祖先。

如果不是同乙個點,那麼就兩個點一起同時往上跳,直到發現兩個點相同,則此時到達的這個結點為x,y兩點的最近公共祖先。

484很簡單?qwq

那我等下放個**,就醬紫吧

int lca(int x,int

y)

其實還有一種暴力的方法

就是先讓其中乙個點一路跳到根結點,標記經過的結點,然後另乙個點也往上跳,遇到的第乙個標記了的結點就是lca

同樣放下**

int lca(int x,int

y)

while(!visit[y])//

如果遇到被標記了的就找到了lca

y=fa[y];

return

y;}

go back

三、倍增法求lca

這是乙個非常重要的演算法啦!一定要記住qaq

我來講一講啦

【預處理】

設f[x][k]表示x結點的2k輩祖先,即從x向根結點走2k步到達的結點

如果該結點不存在,則令f[x][k]=0,f[x][0]就是x的父親結點

因為2k=2k-1+2k-1,所以對於1≤k≤logn,有f[x][k]=f[f[x][k-1]][k-1]

預處理部分的時間複雜度為o(nlongn)

void ready(int x,int

father)

}

【查詢lca】

預處理過後可以對多個x,y查詢lca,每次的時間複雜度均為o(nlogn)

具體操作如下:

1.假設dep[x]≥dep[y],如果不成立可以交換

2.用二進位制拆分思想把x上調到與y同一深度

其實就是依次嘗試讓x向上跳k=2logn...21,20步,若到達的結點比y深,則令x=f[x][k]

3.和上面說的一樣,若此時x與y相等,則y就是lca

4.若此時x≠y,那麼x和y同時往上跳,同樣用二進位制拆分思想,把x和y同時向上跳,並保持深度一致且不相會

與上面調整x時一樣,讓x和y嘗試向上走k=2logn...21,20步,若f[x][k]≠f[y][k](即兩點不相會),則令x=f[x][k],y=f[y][k]

5.結束時x和y必然只差一步就相會了,所以他們的父節點f[x][0]就是lca啦!qwq

int lca(int x,int

y) back(i,

20,0

)

return f[x][0

];}

最後再放乙個完整版**吧qwq

1 #include2

#define go(i,a,b) for(register int i=a;i<=b;i++)

3#define back(i,a,b) for(register int i=a;i>=b;i--)

4using

namespace

std;

5const

int n=100002;6

intn,m;

7int

dep[n],head[n];

8int f[n][20];9

int next[n*2],to[n*2],num=0;10

int last=0;11

intfr()

18while(ch<='

9'&&ch>='0'

)19 w=(w<<1)+(w<<3)+ch-'

0',ch=getchar();

20return w*q;21}

22void ready(int x,int

father)32}

33int lca(int x,int

y)39 back(i,19,0)43

return f[x][0

];44}45

intmain()

58 ready(root,0

);59 m=fr();

60while(m--)

65return0;

66 }

**戳這裡

go back

四、樹鏈剖分求lca

咕咕咕咕咕

go back

五、lca典型例題

咕咕咕咕

go back

LCA學習筆記

在有根樹中 包括二叉樹和其他各種樹 兩個節點ta tb的共同祖先中和兩個節點最近的那個被稱為最近共同祖先 lca,lowest common ancestor 比如上面這張圖中 2和8的lca是1 7和5的lca是5 5和6的lca是3 先從最簡單的想法出發去找兩個點 w和u 的lca,也就是一步一...

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 ...