Cod sursa(job #1284957)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 6 decembrie 2014 23:33:59
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.62 kb
#include <bits/stdc++.h>

using namespace std;

const int Nmax = 100000 + 1;
const int LG = 17;

typedef struct
{
    int nod;
    int urm;

} lista;

lista G[Nmax];
int vecini[Nmax];

int dad[LG][Nmax];
int depth[Nmax], LOG[Nmax];

int N, M;

void addEdge( int x, int y, int i )
{
    G[i].nod = y;
    G[i].urm = vecini[x];
    vecini[x] = i;
}

void DFS( int nod )
{
    for ( int p = vecini[nod]; p != 0; p = G[p].urm )
    {
        int v = G[p].nod;

        depth[v] = depth[nod] + 1;

        DFS( v );
    }
}

void build()
{
    depth[1] = 1;

    DFS( 1 );

    for ( int i = 2; i < Nmax; ++i )
        LOG[i] = LOG[i / 2] + 1;

    for ( int i = 1; ( 1 << i ) <= N; ++i )
        for ( int j = 1; j <= N; ++j )
            dad[i][j] = dad[i - 1][ dad[i - 1][j] ];
}

int lca( int x, int y )
{
    if ( depth[y] < depth[x] ) /// urc cu y
        swap( x, y );

    int logX = LOG[ depth[x] ];
    int logY = LOG[ depth[y] ];

    for ( int k = logY; k >= 0; k-- )
        if ( depth[y] - ( 1 << k ) >= depth[x] )
            y = dad[k][y];

    if ( x == y )
        return x;

    for ( int k = logX; k >= 0; k-- )
        if ( dad[k][x] && dad[k][x] != dad[k][y] )
        {
            x = dad[k][x];
            y = dad[k][y];
        }

    return dad[0][x];
}

int main()
{
    ifstream in("lca.in");
    ofstream out("lca.out");

    ios_base::sync_with_stdio( false );

    in >> N >> M;

    for ( int i = 2; i <= N; ++i )
    {
        in >> dad[0][i];
        addEdge( dad[0][i], i, i - 1 );
    }

    build();

    for ( int i = 0, a, b; i < M; ++i )
    {
        in >> a >> b;
        out << lca( a, b ) << "\n";
    }

    return 0;
}