倍增求LCA模板

不想你离开。 提交于 2020-02-08 20:03:35
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 5;
const int maxm = 1e6 + 5;
struct edge {
    int next, v;
}E[maxm];
int head[maxn];
int tot = 0;
int root;
void addedge(int u, int v) {
    E[++tot].next = head[u];
    E[tot].v = v;
    head[u] = tot;
}
int dep[maxn];
int pa[maxn][25];
void dfs(int u, int depth) {
    dep[u] = depth;
    for (int i = head[u]; i; i = E[i].next) {
        int v = E[i].v;
        if (!dep[v] && v != root) {
            pa[v][0] = u;
            dfs(v, depth + 1);
        }
    }
}
void getparent(int n) {
    for (int j = 1; j <= 20; j++) {
        for (int i = 1; i <= n; i++) {
            pa[i][j] = pa[pa[i][j - 1]][j - 1];
        }
    }
}
int lca(int u, int v) {
    if (dep[u] < dep[v]) {//保证u比v深
        swap(u, v);
    }
    int i = -1;
    while (1 << (i + 1) <= dep[u]) {//确定最大跨度,保证不会越界
        i++;
    }
    for (int j = i; j >= 0; j--) {//让u,v到达同一高度
        if (dep[u] - (1 << j) >= dep[v]) {
            u = pa[u][j];
        }
    }
    if (u == v) {
        return u;
    }
    for (int j = i; j >= 0; j--) {
        if (pa[u][j] != pa[v][j]) {
            u = pa[u][j];
            v = pa[v][j];
        }
    }
    return pa[u][0];
}
void debug(int* a, int l, int r) {
    for (int i = l; i <= r; i++)cout << a[i] << " "; cout << endl;
}
int main() {
    int n, m;
    cin >> n >> m >> root;
    for (int i = 1; i <= n - 1; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        addedge(u, v);
        addedge(v, u);
    }
    dfs(root, 0);
    getparent(n);
    for (int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        int ans = lca(u, v);
        printf("%d\n", ans);
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!