學習筆記 lca 倍增

2022-05-31 04:57:19 字數 1051 閱讀 3342

求一棵樹上兩個節點的最近公共祖先有兩種演算法:

\(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]][j-1]&j>0,i\not=root\end\)

每次查詢兩個節點\(x,y\)的\(lca\)時,現將深度深的點向上移,直到兩個點的深度一樣.

接下來就重複以下工作,直到存在\(f[x][0]=f[y][0]\):

找到最小的\(i\)使得\(f[x][i]=f[y][i]\),如果\(i>0\),則令\(x=f[x][i-1],y=f[y][i-1]\).

(這樣的話能保證找到\(lca\),因為\(f[x][i]\)為公共祖先,\(f[x][i-1]\)不是公共祖先,那麼\(lca\)會在\(father[f[x][i-1]]\)到\(father[f[y][i-1]]\)的路徑上,所以需要退一級尋找.)

#include#include#include#include#include#include#include#include#include#include#define k 20

#define n 10005

#define m 100005

using namespace std;

struct graphe[m];

int f[n][k],g[n],dep[n],m,n,q,cnt;

stacks;

inline void addedge(int x,int y)

inline void dfs(int u)

inline int lca(int x,int y)

}inline void init()

scanf("%d",&q);dfs(1);

for(int i=1,j,k;i<=q;i++)

}int main()

《學習筆記》 倍增 lca

例題 codevs 2370 小機房的樹 簡單來說就是給你乙個n個點的樹,每一條邊都有邊權。詢問有m次,每次給出兩個點,求他們之間的最小邊權和。很容易想到用求樹上字首和和lca,先把兩個點跳到高度相同的地方,再一直往上跳,直到兩個點重合。因為乙個點乙個點的跳太慢了,所以我們倍增的跳來求lca。令f ...

LCA 倍增 學習小結

lca問題,即lowest common ancestor 最近公共祖先 lca問題有很多解法,比如 暴力解法 分塊解法 倍增演算法 tarjan演算法 lct演算法 在這裡呢,我們只討論倍增 倍增演算法其實是一種類似於dp的實現 pa i j p a i j 表示i號節點的2j 2 j個父親 pa...

倍增LCA複習

時間過去了如此之久,我連倍增lca都不怎麼記得了,要粗事啊。首先預處理層數和每個節點的父親,然後預處理p陣列,p i,j 表示i向上第2 j個祖先。最後對於每個詢問x,y先把x,y變成同一層數的 x或y向上走直到兩個層數相等 然後x,y同時向上走,直到x和y的父親相同位置。自 1.dfs預處理出所有...