倍增法求最近公共祖先
时间: 2025-06-22 09:39:16 AIGC 浏览: 29
### 使用倍增法求解最近公共祖先 (LCA) 的算法实现与解释
#### 算法概述
倍增法是一种高效的动态规划技术,适用于处理静态树结构中的查询问题。该方法通过预先计算并存储每个节点的第 \(2^i\) 层祖先来加速后续查询过程。
#### 数据预处理阶段
为了能够快速定位任意两点间的最近公共祖先,在初始化时需构建辅助数组 `f` 和记录各顶点深度的数组 `depth` 。其中 `f[u][j]` 表示从节点 u 出发经过 \(2^j\) 步所能到达的父亲节点位置;当 j=0 时表示直接父亲节点的位置。
```cpp
void dfs(int node, int parent){
depth[node]=depth[parent]+1;
f[node][0]=parent; // 初始化每一点的第一层祖先为自己真正的父节点
for(int i = 1 ;(1<<i)<=depth[node];++i)
f[node][i]=f[f[node][i-1]][i-1];
for(auto child : adj[node])
if(child!=parent)
dfs(child,node);
}
```
上述代码片段实现了自底向上的遍历操作,并完成了对 `f[][]` 数组以及 `depth[]` 数组的填充工作[^1]。
#### 查询函数设计
在完成数据准备之后就可以编写具体的询问逻辑了:
1. **调整两结点至相同高度**
如果两个待查节点不在同一层次,则先让较深的那个往上跳若干步直至两者处于平行状态为止;
2. **同步上升寻找共同祖先**
接着利用之前建立起来的信息表不断尝试使二者同时沿路径返回根部方向移动,直到它们首次交汇于某处即为目标答案所在之处。
3. **特殊情况判断**
若其中一个目标本身就是另一个的目标之一则无需执行第二步流程可直接给出结论。
下面是完整的 C++ 版本实现方式:
```cpp
int lca_query(int a,int b){
if(depth[a]<depth[b]) swap(a,b); // 让a成为更深的一个点
for(int k=logn;k>=0;--k){ // 将a提升到b的高度
if((depth[a]-depth[b])&(1<<k))
a=f[a][k];
}
if(a==b)return a;
for(int k=logn;k>=0;--k){
if(f[a][k]!=f[b][k]){
a=f[a][k];
b=f[b][k];
}
}
return f[a][0];
}
```
此段程序展示了如何基于前期准备工作高效地获取指定节点之间的最低公共祖先关系[^4]。
阅读全文
相关推荐


















