lca学习笔记
首先lca是树上两个节点的最近公共祖先,也就是两个节点的公共祖先中最深的那个。(祖先的定义都知道吧)
最简单的是倍增算法。
倍增
朴素算法是一层层往上跳,而倍增是每次跳\(2^i\)次,大大减少了跳跃次数。
预处理
我们需要两个数组:第\(2^j\)个祖先和它的深度。
实现
首先让两个节点深度相同(往上跳),然后一起往上跳直到两点第一次重合,这就是最近公共祖先。
点击查看代码
void dfs(int i , int fn){
fa[i][0] = fn , deep[i] = deep[fn] + 1;
for(int j=1;j<31;j++){
fa[i][j] = fa[fa[i][j-1]][j-1];
}
for(int j=0;j<vec[i].size();j++){
if(vec[i][j]==fn)continue;
dfs(vec[i][j],i);
}
}
int lca(int x , int y){
if(deep[x]>deep[y])swap(x,y);
int tmp = deep[y] - deep[x];
for(int j=0;tmp;j++,tmp>>=1){
if(tmp&1)y = fa[y][j];
}
if(y==x)return x;
int j;
for(j=30;j>=0&&y!=x;j--) {
if(fa[x][j]!=fa[y][j]){
x = fa[x][j] , y = fa[y][j];
}
}
return fa[x][0];
}

浙公网安备 33010602011771号