Poj1330Nearest Common Ancestors LCA

题意给一颗树,再给一个查询两点之间的最近公共祖先。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
using namespace std;
const int maxn = 111111;

struct edge
{
    int to; int next;
}e[maxn * 10];
int len;
int head[maxn];
struct Node
{
    int val; int id;
}vis[maxn], dp[maxn][20];
int pos[maxn];
int cnt;
void add(int from, int to)
{
    e[len].to = to;
    e[len].next = head[from];
    head[from] = len++;
}

void dfs(int x, int val)
{
    vis[cnt].val = val; vis[cnt].id = x; pos[x] = cnt++;
    for (int i = head[x]; i != -1; i = e[i].next){
        int cc = e[i].to;
        dfs(cc, val + 1);
        vis[cnt].val = val; vis[cnt].id = x; pos[x] = cnt++;
    }
}

void init(int k)
{
    for (int i = 0; i < k; i++)
        dp[i][0] = vis[i];
    for (int j = 1; (1 << j) <= k; j++){
        for (int i = 0; i + (1 << j) - 1 < k; i++){
            if (dp[i][j - 1].val < dp[i + (1 << (j - 1))][j - 1].val)
                dp[i][j] = dp[i][j - 1];
            else dp[i][j] = dp[i + (1 << (j - 1))][j - 1];
        }
    }
}

int ask(int l, int r)
{
    int k = 0;
    while ((1 << (k + 1)) < r - l + 1) k++;
    if (dp[l][k].val < dp[r - (1 << k) + 1][k].val) return dp[l][k].id;
    else return dp[r - (1 << k) + 1][k].id;
}
int main()
{

    int T; int n;
    cin >> T;
    int root;
    int gg[maxn];
    int a, b;
    while (T--){
        cin >> n;
        len = 0;
        memset(head, -1, sizeof(head));
        for (int i = 1; i <= n; i++) gg[i] = 0;
        for (int i = 0; i<n - 1; i++){
            scanf("%d%d", &a, &b);
            add(a, b); gg[b] = 1;
        }
        for (int i = 1; i <= n; i++) if (!gg[i]) {
            root = i; break;
        }
        cnt = 0;
        dfs(root, 1);
        init(cnt);
        cin >> a >> b;
        int l = pos[a]; int r = pos[b];
        if (l>r) swap(l, r);
        cout << ask(l, r) << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yigexigua/p/4083566.html