51nod2599 最近公共祖先LCA

给定一颗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;
}
posted @ 2024-03-19 22:21  chenfy27  阅读(5)  评论(0编辑  收藏  举报