LCA
概念讲解
什么是 LCA?
最近公共祖先(Lowest Common Ancestor)是树上两点最近的公共祖先。
应用
- 求树上两点距离
- 求树上路径
- 树上差分
倍增法
思路
- 预处理每个节点的 级祖先
- 先将两点调整到同一深度
- 再一起向上跳
代码
123456789101112131415161718192021222324252627const int LOG = 20;
int parent[N][LOG], depth[N];
void build(int n) {
for (int j = 1; j < LOG; j++) {
for (int i = 1; i <= n; i++) {
parent[i][j] = parent[parent[i][j-1]][j-1];
}
}
}
int lca(int u, int v) {
if (depth[u] < depth[v]) swap(u, v);
for (int j = LOG-1; j >= 0; j--) {
if (depth[u] - (1 << j) >= depth[v]) {
u = parent[u][j];
}
}
if (u == v) return u;
for (int j = LOG-1; j >= 0; j--) {
if (parent[u][j] != parent[v][j]) {
u = parent[u][j];
v = parent[v][j];
}
}
return parent[u][0];
}树上距离
123int dist(int u, int v) {
return depth[u] + depth[v] - 2 * depth[lca(u, v)];
}考点分析
初赛考查方式
- 程序阅读: LCA 算法
- 编程题: 树上问题
常见考点
- LCA 倍增法
- 树上距离
- 树上路径
例题精讲
例题 1:LCA
题目: 求树上两点的 LCA。
解答:
使用倍增法,先对齐深度再一起上跳。
练习题
- LCA 的作用是什么?
查看答案
LCA 的作用:
- 求树上两点距离:
dist(u,v) = depth[u] + depth[v] - 2*depth[lca(u,v)] - 求树上路径:u → LCA → v
- 树上差分:路径上的点权修改
- 倍增法的时间复杂度是多少?
查看答案
- 预处理:
- 单次查询:
- 如何用 LCA 求树上距离?
查看答案
123int dist(int u, int v) {
return depth[u] + depth[v] - 2 * depth[lca(u, v)];
}原理:u 到 v 的距离 = u 到根的距离 + v 到根的距离 - 2 × LCA 到根的距离
易错点
⚠️ 注意:
- 先对齐深度
- 从大到小枚举
- 注意边界条件
- LCA 是树上问题的基础