lca倍增
lca需要查询两个点的最近公共祖先,使用倍增预处理时间复杂度为O(nlogn),查询为O(logn)
点击查看代码
vector<int> dep; //记录树的深度
vector<vector<int>> up; //记录倍增下第i个数的第第2^j级个祖先
vector<vector<int>> tree; //要处理的树
int VAL=32; //设定二进制分解的最大值
//dfs处理得到up数组
void lcadfs(int x,int las){
up[x][0]=las; //将第一个祖先保存在第0个
dep[x]=dep[las]+1; //递推深度=父节点深度+1
//通过已有祖先来递推自己的祖先
for(int i=1;i<VAL;++i){
up[x][i]=up[up[x][i-1]][i-1];
}
//继续dfs处理
for(auto v:tree[x]){
if(v!=las){
lcadfs(v,x);
}
}
}
//查询lca核心函数
int get_lca(int x,int y){
//1.将深度较深的点跳跃到两点深度齐平
if(dep[x]<dep[y])swap(x,y);
int len=dep[x]-dep[y];
for(int i=VAL-1;i>0;--i){
if(len&(1<<i)){
x=up[x][i];
}
}
if(x==y)return x; //深度齐平时为同一个点,那么最近公共祖先就是当前点
//2.两点同时向上跳跃,找到最近公共祖先
for(int i=VAL-1;i>=0;--i){ //从大往小跳跃能保证找到的lca不会超过正确的lca
if(up[x][i]!=up[y][i]){
x=up[x][i];
y=up[y][i];
}
}
return up[x][0]; //最终停在lca的下一层,所以返回父节点
}

浙公网安备 33010602011771号