概述
對於有根樹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 深 每次檢查中,若是,...