1#include<bits/stdc++.h>
2using namespace std;
3
4const int N = 500010, LOG = 20;
5vector<int> g[N]; // 邻接表存树
6int dep[N], f[N][LOG]; // dep=深度, f[i][j]=节点i的第2^j级祖先
7
8// DFS预处理:求深度 + 倍增表
9void dfs(int u, int fa) {
10 f[u][0] = fa; // 第 2^0=1 级祖先就是直接父亲
11 for (int j = 1; j < LOG; j++)
12 f[u][j] = f[f[u][j-1]][j-1]; // 倍增核心:2^j = 2^(j-1) + 2^(j-1)
13 for (int v : g[u])
14 if (v != fa) {
15 dep[v] = dep[u] + 1; // 子节点深度 = 父+1
16 dfs(v, u);
17 }
18}
19
20// 把节点 x 向上跳 k 步
21int lift(int x, int k) {
22 for (int j = 0; j < LOG; j++)
23 if (k >> j & 1) // k的二进制第j位为1时跳2^j步
24 x = f[x][j];
25 return x;
26}
27
28// 求 u 和 v 的最近公共祖先
29int lca(int u, int v) {
30 if (dep[u] < dep[v]) swap(u, v); // 保证u更深
31 u = lift(u, dep[u] - dep[v]); // 第一步:把u跳到和v同一深度
32 if (u == v) return u; // 巧合就是LCA
33 for (int j = LOG-1; j >= 0; j--) // 从大到小尝试跳
34 if (f[u][j] != f[v][j]) { // 还没相遇就跳
35 u = f[u][j];
36 v = f[v][j];
37 }
38 return f[u][0]; // 最后跳一步到LCA
39}
40
41int main() {
42 int n = 7, m = 5, root = 1;
43 // 建树:1-2, 1-3, 2-4, 2-5, 3-6, 3-7
44 int edges[][2]={{1,2},{1,3},{2,4},{2,5},{3,6},{3,7}};
45 for (auto& e : edges) { // 无向边,双向加
46 g[e[0]].push_back(e[1]);
47 g[e[1]].push_back(e[0]);
48 }
49 dfs(root, 0); // 从根开始预处理
50
51 printf("LCA(4,5) = %d\n", lca(4,5)); // 输出 2
52 printf("LCA(4,6) = %d\n", lca(4,6)); // 输出 1
53 printf("LCA(6,7) = %d\n", lca(6,7)); // 输出 3
54 return 0;
55}
56# 输出: LCA(4,5)=2, LCA(4,6)=1, LCA(6,7)=3