1. 树上倍增与LCA算法基础
最近在刷算法题时遇到一类高频考点——需要快速查询树结构中任意两节点的最近公共祖先(LCA)。这类问题在算法竞赛和实际工程中都很常见,比如社交网络的关系分析、文件系统的目录结构处理等场景。今天我就来分享一个经过实战检验的树上倍增+LCA实现模板。
树上倍增算法的核心思想是通过预处理每个节点的2^k级祖先,将LCA查询的时间复杂度从O(n)优化到O(logn)。这种"空间换时间"的思路在树结构处理中非常实用。我们先看个简单例子:假设要查询节点u和v的LCA,可以先将较深的节点u跳到与v同深度,然后两者一起向上跳,直到找到第一个公共祖先。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 算法实现细节解析
2.1 数据结构设计
首先需要定义树的存储结构。我推荐使用邻接表来存储树,对于n个节点的树,可以这样定义:
cpp复制const int MAXN = 1e5 + 5; // 最大节点数
vector<int> tree[MAXN]; // 邻接表存储树结构
int depth[MAXN]; // 每个节点的深度
int up[MAXN][20]; // up[i][j]表示i节点的2^j级祖先
这里up数组就是倍增算法的核心,第二维大小取20是因为2^20足够覆盖大多数场景(约100万节点)。
2.2 预处理阶段实现
预处理采用DFS遍历,同时记录每个节点的深度和倍增祖先:
cpp复制void dfs(int u, int parent) {
up[u][0] = parent; // 直接父节点
for(int i = 1; i < 20; i++) {
up[u][i] = up[up[u][i-1]][i-1]; // 倍增思想核心
}
for(int v : tree[u]) {
if(v != parent) {
depth[v] = depth[u] + 1;
dfs(v, u);
}
}
}
这个预处理的时间复杂度是O(nlogn),因为每个节点需要处理20个祖先信息。
