最近公共祖先(LCA)
1.算法笔记 - 树的直径
2.最近公共祖先(LCA)
定义 性质:
在有根树上,
-
具有可并性。 -
在 间的路径上。 -
设
表示 与根的距离,则两点 的距离 。
求法:
倍增。
设
到最后时,
预处理
时间复杂度:设询问
代码:
#include<iostream> #include<vector> #define int long long using namespace std; const int N = 500010; int lg[N]; int n, m, rt; vector<int> G[N]; int de[N], fa[N][25]; void dfs(int fat, int u) // 预处理 { fa[u][0] = fat; de[u] = de[fat] + 1; // 初始化 for(int i=1; i<=lg[de[u]]; i++) fa[u][i] = fa[fa[u][i-1]][i-1]; // 转移 for(int i=0; i<G[u].size(); i++) { int v = G[u][i]; if(v == fat) continue; dfs(u, v); // 搜索 } } int LCA(int x, int y) { if(de[x] < de[y]) // 保证y深于x,便于计算 swap(x, y); while(de[x] > de[y]) x = fa[x][lg[de[x] - de[y]] - 1]; // 统一深度 if(x == y) return x; // 特判 for(int k=lg[de[x]]-1; k>=0; k--) if(fa[x][k] != fa[y][k]) x = fa[x][k], y = fa[y][k]; // 跳转到LCA的下方 return fa[x][0]; } signed main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); for(int i=1; i<N; i++) lg[i] = lg[i-1] + ((1 << lg[i-1]) == i); cin >> n >> m >> rt; for(int i=1; i<n; i++) { int u, v; cin >> u >> v; G[u].push_back(v); G[v].push_back(u); } dfs(0, rt); while(m --) { int x, y; cin >> x >> y; cout << LCA(x, y) << '\n'; } return 0; }
本文作者:gctiruct
本文链接:https://www.cnblogs.com/gctiruct/p/18100841
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步