Cod sursa(job #2529950)

Utilizator nicolaefilatNicolae Filat nicolaefilat Data 24 ianuarie 2020 10:46:39
Problema Lowest Common Ancestor Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.12 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>

const int MAXN = 1e5 + 1;

using namespace std;

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

vector<int>graf[MAXN];/// retine graful de la radacina spre frunze
vector<int>lant[MAXN];
int tata[MAXN],nod_lant[MAXN],nr_lanturi;
bool viz[MAXN];
int n,dimensiune[MAXN],inaltime_lant[MAXN];
int pozitie_lant[MAXN];


void dfs(int nod){
    dimensiune[nod] = 1;
    viz[nod] = true;
    int curent;
    for(int i = 0; i < graf[nod].size(); i++){
        curent = graf[nod][i];
        if(!viz[curent]){
            dfs(curent);

            dimensiune[nod] += dimensiune[curent];
        }
    }
    if(graf[nod].size() == 0){
        /// este frunza
        lant[++nr_lanturi].push_back(nod);
        pozitie_lant[nod] = 0;/// in vectorul de lant se afla pe pozitia 0,prima pozitie
        nod_lant[nod] = nr_lanturi;
    }else{
        /// are toti vecinii vitati
        int vecin_bun;
        int maxim = 0;
        for(int i = 0; i < graf[nod].size(); i++){
            int vecin = graf[nod][i];
            if(dimensiune[vecin] > maxim){
                maxim = dimensiune[vecin];
                vecin_bun = vecin;
            }
        }
        /// am gasit vecinul cu subarborele maxim
        int unde = nod_lant[vecin_bun];
        lant[unde].push_back(nod);
        pozitie_lant[nod] = lant[unde].size() - 1;/// in vectorul lant nod se afla pe ultima pozitie.
        nod_lant[nod] = unde;

    }
}
void dfs_inaltime_lant(int nod){
    viz[nod] = true;

    int unde_nod = nod_lant[nod];

    for(int i = 0; i < graf[nod].size(); i++){
        int curent = graf[nod][i];
        int unde_curent = nod_lant[curent];
        if(!viz[curent]){

            if(unde_curent != unde_nod){

                inaltime_lant[unde_curent] = inaltime_lant[unde_nod] + 1;
                ///cout<<curent<<" "<<nod<<" "<<inaltime_lant[unde_curent]<<" "<<unde_curent<<endl;
            }
            dfs_inaltime_lant(curent);
        }
    }

}
void lca(int a,int b){
    int index_lant_a = nod_lant[a];
    int index_lant_b = nod_lant[b];

    /// vreau a > b
    if(inaltime_lant[index_lant_a] < inaltime_lant[index_lant_b]){
        swap(a,b);
        swap(index_lant_a,index_lant_b);
    }
    while(inaltime_lant[index_lant_a] > inaltime_lant[index_lant_b]){
        /// urc a pe lant
        int ultim_nod = lant[index_lant_a].back();
        a = tata[ultim_nod];
        index_lant_a = nod_lant[a];
    }
    while(nod_lant[a] != nod_lant[b]){
        int ultim_nod = lant[index_lant_a].back();
        a = tata[ultim_nod];
        index_lant_a = nod_lant[a];
        ultim_nod = lant[index_lant_b].back();
        b = tata[ultim_nod];
        index_lant_b = nod_lant[b];
    }
    /// sunt in acelasi lant => urc folosind pozitie_lant[]
    /// pozitiile in lant vin de jos in sus.
    /// pozitia 0 inseamna cel mai de jos, pozitia size() - 1 inseamna cel mai de sus
    /// eu vreau ca a sa fie mai jos ca b => poz[a] < poz[b]
    /// daca nu e asa dau swap
    //cout<<a<<" "<<b<<endl;
    //cout<<pozitie_lant[a]<<" "<<pozitie_lant[b]<<endl;
    if(pozitie_lant[a] > pozitie_lant[b])
        swap(a,b);
    while(pozitie_lant[a] < pozitie_lant[b]){
        a = tata[a];
    }
    out<<a<<"\n";
}



int main()
{

    int intrebari;
    in>>n>>intrebari;
    for(int i = 1; i <= n - 1; i++){
        in>>tata[i + 1];
        graf[tata[i + 1]].push_back(i + 1);
        ///cout<<tata[i + 1]<<" merge in "<<i + 1<<endl;
    }
    dfs(1);
    inaltime_lant[1] = 1;
    for(int i = 1; i <= n; i++)
        viz[i] = false;
    dfs_inaltime_lant(1);
//    cout<<endl;
//    for(int i = 1; i <= nr_lanturi; i++){
//        for(int j = 0; j < lant[i].size(); j++){
//            int curent = lant[i][j];
//            cout<<curent<<" ";
//            if(j + 1 == lant[i].size())
//                cout<<"Inaltime : "<<inaltime_lant[i];
//        }
//        cout<<endl;
//    }
    for(int i = 1; i <= intrebari; i++){
        int a,b;
        in>>a>>b;
        lca(a,b);
    }
    return 0;
}