LCA 简介
LCA(Least Common Ancestors,最近公共祖先)是树结构中的核心概念,指两个节点所有公共祖先中距离它们最近(深度最大)的节点。
核心定义
- 祖先:树中从当前节点到根节点路径上的所有节点,自身也可视为自己的祖先。
- 公共祖先:同时是两个节点祖先的节点。
- 最近公共祖先:在所有公共祖先中,深度最深的那个节点(距离两个节点路径长度之和最小)。
应用场景
- 树结构查询:如二叉树中两个节点的路径长度计算(路径长度 = 节点 A 到 LCA 的距离 + 节点 B 到 LCA 的距离)。
- 图论与算法:处理树形结构的拓扑关系,比如网络路由优化、家谱关系查询、XML/HTML 文档结构解析。
- 工程实践:编译器语法树分析、数据库索引树(如 B 树)的节点关联查询。
关键特性
- 唯一性:在一棵有根树中,任意两个节点的 LCA 有且仅有一个。
- 路径特性:两个节点的最短路径必然经过它们的 LCA,且 LCA 是路径上的中间关键点。
- 根节点关联:若一个节点是另一个节点的祖先,则该节点就是两者的 LCA。
求 LCA 的方法
方法一:朴素求 LCA(倍增求 LCA)
要求 LCA,应先求出每个点的深度(用 DFS)。朴素的求 LCA 方法是:不妨设 x 为深度更深的点,不断让 x 往上爬,直到 dep[x] == dep[y]。如果 x == y 就返回,如果不等于就让 x 和 y 一起往上跳,直到 x == y 再返回。思路简单,但复杂度高。因此有了倍增法求 LCA:本质上是 DP,类似 ST 表,fa[i][j] 表示 i 号节点往上走 2^j 所到的节点,当 dep[i] - 2^j >= 1 时 fa[i][j] 有效(设根节点深度为 1)。
例如:
1 | 2 | 3 | 4 \ 5
fa[5][0] = 4 (从 5 向上走 2^0),fa[5][1] = fa[fa[5][0]][0] = 3
代码
void dfs(int x, int p) // p:父节点 {
dep[x] = dep[p] + 1;
fa[x][0] = p;
for (int i = 1; i <= 20; i++) {
fa[x][i] = fa[fa[x][i - 1]][i - 1];
}
for (const auto& y : g[x]) {
if (y == p) continue;
dfs(y, x);
}
}
{
(dep[x] < dep[y]) (x, y);
( i = ; i >= ; i--) {
(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
}
(x == y) x;
( i = ; i >= ; i--) {
(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
}
fa[x][];
}


