Cod sursa(job #1501445)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 13 octombrie 2015 14:09:44
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.69 kb
#include <cstdio>
#include <algorithm>

using namespace std;

const int Nmax = 100000 + 1;
const int lgMax = 17;
const int NIL = -1;

int d[lgMax][Nmax];
int depth[Nmax];

struct List {
    int v, next;
};

List l[Nmax];
int adj[Nmax];

void addEdge(int u, int v, int pos) {
    l[pos].v = v;
    l[pos].next = adj[u];
    adj[u] = pos;
}

void DFS(int u) {
    for (int i = adj[u]; i != NIL; i = l[i].next) {
        int v = l[i].v;
        depth[v] = depth[u] + 1;
        DFS(v);
    }
}

int main(void) {
    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);
    int n, m;
    int u, v;

    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        adj[i] = NIL;
    }
    for (int i = 2; i <= n; i++) {
        scanf("%d", &d[0][i]);
        addEdge(d[0][i], i, i - 1);
    }

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

    depth[1] = 1;
    DFS(1);

    for (int i = 0; i < m; i++) {
        scanf("%d%d", &u, &v);
        if (depth[u] > depth[v]) {
            swap(u, v);
        }
        for (int k = 31 - __builtin_clz(depth[v]); k >= 0; k--) {
            if (depth[v] - (1 << k) >= depth[u]) {
                v = d[k][v];
            }
        }
        if (u != v) {
            for (int k = 31 - __builtin_clz(depth[u]); k >= 0; k--) {
                if (d[k][u] && d[k][u] != d[k][v]) {
                    u = d[k][u];
                    v = d[k][v];
                }
            }
            u = d[0][u];
        }
        printf("%d\n", u);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}