LCA 最近公共祖先)之倍增演算法

2022-04-30 08:45:14 字數 1443 閱讀 2245

概述

對於有根樹t的兩個結點u、v,最近公共祖先lca(t,u,v)表示乙個結點x,滿足x是u、v的祖先且x的深度盡可能大。

如圖,3和5的最近公共祖先是1,5和2的最近公共祖先是4

在本篇中我們先介紹一下倍增演算法

我們需要乙個陣列de[i]來表示每乙個節點i的深度,用另一陣列parent[i][j]來表示每一節點j向上走2的i次方是哪個節點

我們首先在初始化中算出每個點的深度和它的上乙個點是什麼(用parent[0][i]表示)

在此後我們進行倍增的處理:parent[1][j]=parent[0][parent[0][j]]......parent[i+1][j]=parent[i][parent[i][j]]

當然如果已經走到根節點了,就將其它的parent全設為0

然後我們就可以搞lca了:給你兩個點想x,y,讓y成為深的那個,如果x,y深度不等就讓y倍增地往上跳。

當x,y深度相等時凡是它倆不相等就倍增地跳,最後它們中任意乙個的父節點及他們的最近公共祖先

模板

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

const int log=20;

int head[1000100],nxt[1000100],to[1000100],cnt;

int de[500010];

int parent[log+3][500010];

inline void read(int &x)

while(s>='0'&&s<='9')

x*=f;

}inline void add(int x,int y)

inline void dfs(int now,int dep,int be)

inline int lca(int x,int y)

int main()

dfs(s,0,0);

for(i=0;i<=log;i++)

for(j=1;j<=n;j++)

if(parent[i][j]<=0)parent[i+1][j]=-1;

else parent[i+1][j]=parent[i][parent[i][j]];

for(i=1;i<=m;i++)

return 0;

}

LCA 最近公共祖先 (倍增演算法)

首先了解一下我們 最近公共祖先 e和g的lca為a l和j的lca為d k和f的lca為b 然後 倍增 用到了二進位制和 dp 的思想 倍增 就是 1 2 4 8 16 任何乙個數 都是可以右 這些數相加得到的。了解一下二進位制 首先 定義 fa i j 為 從 i 節點 向上走 2 j 個節點,d...

最近公共祖先 LCA 倍增演算法

樹上倍增求lca lca指的是最近公共祖先 least common ancestors 如下圖所示 4和5的lca就是2 那怎麼求呢?最粗暴的方法就是先dfs一次,處理出每個點的深度 然後把深度更深的那乙個點 4 乙個點地乙個點地往上跳,直到到某個點 3 和另外那個點 5 的深度一樣 然後兩個點一...

樹,LCA,最近公共祖先,倍增

最近公共祖先,樹上倍增,lca,fa i j 表示 i 節點向上 2j 的祖先 很像dp,k 屬於 1 log n f x k f f x k 1 k 1 算lca時,先不妨設 d x d y 二進位制拆分 嘗試從x 向上走 k 2log n 21,20,檢查到的點是否比 y 深 每次檢查中,若是,...