给定一颗n个节点的树,根节点编号为1,有Q组询问,每次给定一对节点编号(x,y),求(x,y)的最近公共祖先。
求LCA有多种方法,这里给的是倍增法,预处理时间O(nlogn),单次查询时间O(logn),支持在线。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=b;i>=a;i--)
const int N = 500005;
int n, Q, dep[N], fa[N][21];
vector<int> adj[N];
void dfs(int x, int p) {
fa[x][0] = p;
dep[x] = dep[p] + 1;
rep(i,1,20) {
fa[x][i] = fa[fa[x][i-1]][i-1];
}
for (auto i:adj[x]) if (i!=p) {
dfs(i, x);
}
}
int lca(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
per(i,0,20) if (dep[fa[x][i]] >= dep[y]) {
x = fa[x][i];
}
if (x == y) return x;
per(i,0,20) if (fa[x][i] != fa[y][i]) {
x = fa[x][i];
y = fa[y][i];
}
return fa[x][0];
}
void solve() {
cin >> n;
rep(i,1,n-1) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
dfs(1, 1);
cin >> Q;
while (Q--) {
int a, b;
cin >> a >> b;
cout << lca(a,b) << "\n";
}
}
signed main() {
cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}
标签:dep,51nod2599,fa,祖先,cin,dfs,int,LCA,adj
From: https://www.cnblogs.com/chenfy27/p/18084129