Cod sursa(job #925631)

Utilizator Teodor94Teodor Plop Teodor94 Data 24 martie 2013 17:21:35
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.81 kb
#include <cstdio>
#include <cassert>
#include <vector>

using namespace std;

#define MAX_N 100001
#define LOG_MAX_N 20
#define MAX_S 600001

int n, m;
int father[LOG_MAX_N][MAX_N];
vector <int> v[MAX_N];
int level[MAX_N];
char s[MAX_S];

void read() {
    assert(scanf("%d%d\n", &n, &m) == 2);

    gets(s);

    int node = 2;
    for (int i = 0; s[i]; ++i)
        if (s[i] == ' ')
            ++node;
        else
            father[0][node] = father[0][node] * 10 + s[i] - '0';

    for (int i = 2; i <= n; ++i)
        v[father[0][i]].push_back(i);
}

void set_father() {
    for (int j = 1; (1 << j) <= n; ++j)
        for (int i = 1; i <= n; ++i)
            father[j][i] = father[j - 1][father[j - 1][i]];
}

void dfs(int node, int lvl) {
    level[node] = lvl;

    for (vector <int>::iterator it = v[node].begin(); it != v[node].end(); ++it)
        dfs(*it, lvl + 1);
}

int lca(int a, int b) {
    if (a == b)
        return a;

    if (level[a] < level[b])
        swap(a, b);

    int log_a = 1, log_b = 1;

    while (1 << log_a < level[a])
        ++log_a;

    while (1 << log_b < level[b])
        ++log_b;

    for (int i = log_a; i >= 0; --i)
        if (level[a] - (1 << i) >= level[b])
            a = father[i][a];

    if (a == b)
        return a;

    for (int i = log_b; i >= 0; --i)
        if (father[i][a] && father[i][a] != father[i][b]) {
            a = father[i][a];

            b = father[i][b];
        }

    return father[0][a];
}

int main() {
    assert(freopen("lca.in", "r", stdin));
    assert(freopen("lca.out", "w", stdout));

    read();

    set_father();

    dfs(1, 1);

    while (m) {
        int a, b;
        assert(scanf("%d%d", &a, &b) == 2);

        printf("%d\n", lca(a, b));

        --m;
    }
}