Cod sursa(job #3240155)

Utilizator ireallydontcareidontcare ireallydontcare Data 12 august 2024 21:09:42
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.86 kb
#include <fstream>
#include <vector>

using namespace std;

const int MAX_N = 100005;
const int MAX_L = 20;

ifstream fin("lca.in");
ofstream fout("lca.out");

int N, M;
int T[MAX_L][MAX_N]; // T[k][i] este al 2^k-lea strămoș al lui i
int Lg[MAX_N]; // Lg[i] este log2(i)
int Lev[MAX_N]; // Nivelul fiecărui nod în arbore
vector<int> G[MAX_N]; // Lista de adiacență pentru arbore

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

    // Citim arborele, unde T[0][i] este părintele lui i
    for (int i = 2; i <= N; ++i) {
        fin >> T[0][i];
        G[T[0][i]].push_back(i);
    }

    // Precalculăm toți strămoșii folosind DP (Dynamic Programming)
    for (int 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;

    // Explorăm copiii nodului curent
    for (auto& vecin : G[nod]) {
        dfs(vecin, lev + 1);
    }
}

int lca(int x, int y) {
    if (Lev[x] < Lev[y]) {
        swap(x, y); // Ne asigurăm că x este cel mai adânc
    }

    // Ridicăm nodul x la același nivel cu y
    int log1 = 0;
    while ((1 << (log1 + 1)) <= Lev[x]) {
        log1++;
    }

    for (int k = log1; k >= 0; --k) {
        if (Lev[x] - (1 << k) >= Lev[y]) {
            x = T[k][x];
        }
    }

    if (x == y) {
        return x; // Dacă am ajuns la același nod, acesta este LCA
    }

    // Căutăm LCA urcând ambii părinți
    for (int k = log1; k >= 0; --k) {
        if (T[k][x] && T[k][x] != T[k][y]) {
            x = T[k][x];
            y = T[k][y];
        }
    }

    return T[0][x]; // Părintele comun al lui x și y
}

int main() {
    citire();
    dfs(1, 0); // Pornim DFS de la rădăcina arborelui, presupusă a fi nodul 1

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

    return 0;
}