Cod sursa(job #2188939)

Utilizator ruxandramateiMatei Ruxandra ruxandramatei Data 27 martie 2018 16:16:05
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 3.78 kb
#include <iostream>
#include <fstream>
#include <cstring>
#define DMAX 100001

using namespace std;

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

struct elem{
    int val;
    elem *urm;
}* nod[DMAX];

int n, m;//date de intrare
int reprezEuler[DMAX * 4], lg, nivelNod[DMAX], pozInRepr[DMAX];
int lungLog[DMAX], nrIntervale;
int minim[17][DMAX * 4];

void citire(){
    in >> n >> m;
    for(int i = 2; i <= n; i++){
        int tata;
        in >> tata;//citesc tatal nodului i;
        elem * deAdaugat = new elem;
        deAdaugat -> val = i;
        deAdaugat -> urm = nod[tata];
        nod[tata] = deAdaugat; // fac legatura
    }
}

void niveleNoduri(){
    int coada[DMAX], primul, ultimul;
    bool viz[DMAX * 4];
    memset(viz, false, sizeof(viz));
    primul = ultimul = 1;
    coada[1] = 1;
    viz[1] = true;//nodul 1 e radacina
    nivelNod[1] = 0;
    while(primul <= ultimul){
        int actual = coada[primul];
        primul++;//scot din coada
        elem * parcurg = nod[actual];
        while(parcurg != NULL){
            if(viz[parcurg -> val] == false){
                coada[++ ultimul] = parcurg -> val;
                viz[parcurg -> val] = true;
                nivelNod[parcurg -> val]  = nivelNod[actual] + 1;
            }
            parcurg = parcurg -> urm;
        }
    }
}

void reprezentareEuleriana(){ //parcurgere DF
    int stiva[DMAX * 4], vfStiva;
    bool viz[DMAX];
    memset(viz, false, sizeof(viz));
    vfStiva = 1;
    stiva[1] = 1;//1 e radacina
    reprezEuler[++lg] = 1;
    pozInRepr[1] = 1;
    viz[1] = true;
    while(vfStiva != 0){
        int actual = stiva[vfStiva];
        bool ok = false;
        elem * parcurg = nod[actual];
        while (parcurg != NULL){
            if(viz[parcurg -> val] == false){
                stiva[++vfStiva] = parcurg -> val;
                viz[parcurg -> val] = true;
                reprezEuler[++lg] = parcurg -> val;
                if(pozInRepr[parcurg -> val] == 0){
                    pozInRepr[parcurg -> val] = lg;
                }
                ok = true;
                break;
            }
            parcurg = parcurg -> urm;
        }
        if(ok == false){
            vfStiva--;
            reprezEuler[++lg] = stiva[vfStiva];
        }
    }

}

void lungimi(){
    for(int i = 1; i <= lg; i++){
        lungLog[i] = lungLog[i/2] + 1;
    }
    nrIntervale = lungLog[lg] - 1;
}

void sparseTable(){
    for(int i = 1; i <= lg; i++){
        minim[0][i] = reprezEuler[i];
    }
    for(int exLgInter = 1; exLgInter <= nrIntervale; exLgInter++){ //exponentii lgInter
        int limita = 1 << exLgInter;
        for(int index = 1; index + limita <= lg + 1; index++){
            int lin = exLgInter, col = index;
            if(nivelNod[minim[lin - 1][col]] < nivelNod[minim[lin - 1][col + (1 << (exLgInter - 1))]]){
                minim[lin][col] = minim[lin - 1][col];
            }else{
                minim[lin][col] = minim[lin - 1][col + (1 << (exLgInter - 1))];
            }
        }
    }
}

void rezolvare(){
    for(int i = 1; i <= m; i++){
        int a, b, st, dr;
        in >> a >> b;
        if(pozInRepr[a] < pozInRepr[b]){
            st = pozInRepr[a];
            dr = pozInRepr[b] + 1;
        }else{
            st = pozInRepr[b];
            dr = pozInRepr[a] + 1;
        }
        int lungimeInterval = dr - st;
        int incadrare = lungLog[lungimeInterval] - 1;
        int min1, min2;
        min1 = minim[incadrare][st];
        min2 = minim[incadrare][dr - (1 << incadrare)];
        if(nivelNod[min1] < nivelNod[min2]){
            out << min1 << '\n';
        }else{
            out << min2 << '\n';
        }
    }
}

int main() {
    citire();
    niveleNoduri();
    reprezentareEuleriana();
    lungimi();//incep sa fac rmq pe reprezentarea euleriana
    sparseTable();
    rezolvare();
    return 0;
}