Cod sursa(job #1886716)

Utilizator MithrilBratu Andrei Mithril Data 21 februarie 2017 09:06:55
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.03 kb
#include <bits/stdc++.h>
using namespace std;

#define MAX_N 100005
#define MAX_L 20
ifstream fin ("lca.in");
ofstream fout ("lca.out");

int N, M, T[MAX_L][MAX_N], Lev[MAX_N];
vector <int> G[MAX_N];

void citire() {
    fin >> N >> M;

    ///T[i][j] - stramosul aflat la 2^i nivele mai sus ale lui j
    for(int i = 2; i <= N; ++i)
    {
        fin >> T[0][i];
        G[T[0][i]].push_back(i);
    }

    int k;
    ///procesam stramosii unui nod - dupa regula "bunicul este tatal tatalui"
    ///incepem sa procesam de la bunic in sus
    for(k = 1; (1 << k) <= N; ++k)
        for(int i = 1; i <= N; ++i)
            T[k][i] = T[k-1][T[k-1][i]];
}

void dfs(int nod, int lev) {
    Lev[nod] = lev;

    for(auto x:G[nod])
        dfs(x,lev+1);
}

int lca(int x, int y) {
    ///nodul x va fi cel cu nivel mai mare - adica care se afla mai jos in graf
    if(Lev[x] < Lev[y])
        swap(x, y);

    int log1, log2;
    ///orice distanta de la un nod la LCA-ul sau poate fi exprimata ca puteri ale lui 2
    ///folosim log1 si log2 ca sa vedem cat putem urca in arbore "dintr-un foc"
    ///pornim de la 2^1 - este evident ca putem urca in tata ( adica 2^0 )
    for(log1 = 1; (1 << log1) < Lev[x]; ++log1);
    for(log2 = 1; (1 << log2) < Lev[y]; ++log2);

    ///urcam in timp logaritmic pe x la nivelul lui y
    for(int k = log1; k >= 0; --k)
        if(Lev[x] - (1 << k) >= Lev[y])
            x = T[k][x];

    ///y era un stramos al lui x deci LCA-ul lui
    if(x == y) return x;

    ///x si y sunt pe ramuri diferite
    ///vom urca atata timp cat nu ajungem la un stramos comun - deoarece deasupra la LCA amandoi au aceiasi stramosi
    for(int k = log2; k >= 0; --k)
        if(T[k][x] && T[k][x] != T[k][y])
            x = T[k][x],
            y = T[k][y];

    ///am terminat de urcat - tatal lui x si y este LCA
    return T[0][x];
}

int main() {
    citire();
    dfs(1, 0);

    while(M--)
    {
        int x, y;
        fin >> x >> y;
        fout << lca(x, y) << "\n";
    }
}