Cod sursa(job #2181858)

Utilizator Vlad98Popa Vlad-Gabriel Vlad98 Data 21 martie 2018 21:30:31
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.73 kb
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;

int k = 2;


typedef struct nod{
   int* copii;
   int nCopii;
   int k;
   int nMaxCopii;
}TNod;

typedef struct {
    int v, n;
}rmq;

void EulerianPath(int *Euler, int *nivel, TNod *noduri, int *adancime, int *primaAparitie, int x)
{
    while(noduri[x].k < noduri[x].nCopii){
    Euler[k] = noduri[x].copii[noduri[x].k];
    nivel[k] = adancime[x]+1;
    if(!primaAparitie[Euler[k]]) primaAparitie[Euler[k]] = k;
    k++;
    EulerianPath( Euler, nivel, noduri, adancime, primaAparitie, Euler[k-1]);
    Euler[k] = x;
    nivel[k] = adancime[x];
    k++;
    noduri[x].k++;
    }

}
int main()
{
    int n, m, x;
    FILE  *fi, *fo;
    fi = fopen("lca.in", "r");
    fscanf(fi,"%d %d", &n, &m);

    TNod* noduri=(TNod*)malloc((n+1)*sizeof(TNod));
    int N, i, j;

    int* Euler =(int*)malloc((2*n+3)* sizeof(int));
    int* nivel =(int*)malloc((2*n+3)* sizeof(int));
    int* adancime = (int*)malloc((n+1)*sizeof(int));
    int* primaAparitie = (int*)calloc((n+1),sizeof(int));

    adancime[1] = 0;

    for(i = 1; i <= n; i++)
    {  noduri[i].nMaxCopii = 50;
       noduri[i].copii=(int*)malloc(50*sizeof(int));
       noduri[i].nCopii = 0;
       noduri[i].k=0;
    }
    for(i = 2; i <= n; i++)
    {
        fscanf(fi,"%d",&x);
        if(noduri[x].nCopii == noduri[x].nMaxCopii){
            noduri[x].nMaxCopii*=2;
            int* temp=(int*)realloc(noduri[x].copii, noduri[x].nMaxCopii*sizeof(int));
            noduri[x].copii = temp;
            temp = NULL;
        }
        noduri[x].copii[noduri[x].nCopii] = i;
        noduri[x].nCopii++;
        adancime[i] = adancime[x]+1;

    }

    Euler[1] = 1;
    primaAparitie[1]=0;
    nivel[1]=0;
    EulerianPath(Euler, nivel, noduri, adancime, primaAparitie, 1);


    N = k;

    int lg = log2(N);
    rmq** d=(rmq**)malloc((lg+1)*sizeof(rmq*));
    for(i = 0; i < lg+1; i++)
    {
        d[i] =(rmq*)malloc((N+1)*sizeof(rmq));
    }

    for(j = 1; j <= N; j++)
    {
        d[0][j].v =   nivel[j];
        d[0][j].n = Euler[j];
    }
    int y = 1;

    for( i = 1; i <= lg; i++ )
    {

        for(j = 1; j < 2*y; j++)
        {
            d[i][j].v = d[i-1][j].v;
            d[i][j].n = d[i-1][j].n;
        }
        for(; j <= N; j++)
        {

            if(d[i-1][j].v < d[i-1][j - y].v)
            {
                d[i][j].v = d[i-1][j].v;
                d[i][j].n = d[i-1][j].n;

            }
            else{
                d[i][j].v = d[i-1][j - y].v;
                d[i][j].n = d[i-1][j - y].n;
            }
        }
        y*=2;

    }
    int* putere =(int *)malloc((N+2)*sizeof(int));
    putere[1] = 0;
    putere[0] = 0;
    for( i = 2; i <= N; i++)
    {
      putere[i] = putere[i/2] + 1;
    }
    fo = fopen("lca.out", "w");
    for(i = 0; i < m; i++)
    {
        int l , r;
        fscanf(fi,"%d %d", &l, &r);
        l = primaAparitie[l];
        r = primaAparitie[r];
        if(l>r) {
            int aux = l;
            l = r;
            r = aux;
        }
        int len = r - l + 1;
        int p  = putere[len-1];
        int valPutere = (1<<p);
        if(d[p][r].v < d[p][l + valPutere - 1].v)
                    fprintf(fo,"%d\n", d[p][r].n);
            else fprintf(fo,"%d\n", d[p][l + valPutere - 1].n);


    }

    free(putere);
    for(i  = 0; i < lg+1; i++)
        free(d[i]);
    free(d);
    free(putere);
    free(Euler);
    free(adancime);
    free(primaAparitie);
    free(nivel);
    for(i = 1; i <= n; i++){
        free(noduri[i].copii);
    }
    free(noduri);
    fclose(fi);
    fclose(fo);
    return 0;
}