Cod sursa(job #368694)

Utilizator MariusMarius Stroe Marius Data 25 noiembrie 2009 15:48:20
Problema Lowest Common Ancestor Scor Ascuns
Compilator cpp Status done
Runda Marime 1.68 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <cassert>
#include <algorithm>
using namespace std;

const char iname[] = "lca.in";
const char oname[] = "lca.out";

#define MAXN  100005
#define MAXLOG  17

vector <int> adj[MAXN], level(MAXN);

int up[MAXLOG][MAXN], stk[MAXN], stk_len, twoPower[MAXN];;

void DF(int n) {
    vector <int>::iterator it;

    stk[++ stk_len] = n;
    level[n] = stk_len;

    for (int i = 0; (1 << i) < stk_len; ++ i)
        up[i][n] = stk[stk_len - (1 << i)];

    for (it = adj[n].begin(); it != adj[n].end(); ++ it)
        DF(*it);

    --stk_len;
}

bool hasAncestor(int node, int anc) {
    int i;

    while (level[anc] < level[node]) {
        for (i = 0; level[node] - (1 << i) >= level[anc]; ++ i) ;
        node = up[i - 1][node];
    }
    return anc == node;
}

int lca(int x, int y) {
    if (level[x] > level[y])
        swap(x, y);
    if (hasAncestor(y, x))
        return x;
    int delta = twoPower[ level[x] ];
    for (; delta >= 0; -- delta) if (1 << delta < level[x]) {
        if (!hasAncestor(y, up[delta][x]))
            x = up[delta][x];
    }
    return up[0][x];
}

int main(void) {
    ifstream in(iname);
    ofstream out(oname);
    int n, m;

    in >> n >> m;
    for (int i = 2; i <= n; ++ i) {
        int node;
        in >> node;
        adj[node].push_back(i);
    }

    DF(1);

    for (int i = 0; (1 << i) <= n; ++ i)
        twoPower[1 << i] = i;
    for (int i = 3; i <= n; ++ i) if (twoPower[i] == 0)
        twoPower[i] = twoPower[i - 1];

    for (int i = 0; i < m; ++ i) {
        int x, y;
        in >> x >> y;
        out << lca(x, y) << '\n';
    }
    in.close();
    out.close();
    return 0;
}