Cod sursa(job #1414488)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 2 aprilie 2015 17:33:35
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;

vector<int> G[Nmax];

int tata[Nmax];
int depth[Nmax];
int size[Nmax];

int path[Nmax];
int pos_in_path[Nmax];
int length_path[Nmax];
int start_node[Nmax];

int N, Q;
int nrPaths;

void dfs(int nod)
{
    int hson = 0;
    size[nod] = 1;

    for (auto& son: G[nod])
    {
        if (tata[son] == 0)
        {
            tata[son] = nod;
            depth[son] = depth[nod] + 1;
            dfs(son);

            size[nod] += size[son];

            if (size[hson] < size[son])
                hson = son;
        }
    }

    if (hson == 0)
        path[nod] = nrPaths++;
    else
        path[nod] = path[hson];

    pos_in_path[nod] = length_path[ path[nod] ]++;
}

void build_hpd()
{
    tata[1] = 1;
    depth[1] = 0;
    dfs(1);

    for (int i = 1; i <= N; ++i)
    {
        pos_in_path[i] = length_path[ path[i] ] - pos_in_path[i] - 1;

        if (pos_in_path[i] == 0)
            start_node[ path[i] ] = i;
    }
}

int lca(int x, int y)
{
    while (path[x] != path[y])
    {
        if (depth[ start_node[ path[x] ] ] > depth[ start_node[ path[y] ] ])
            x = tata[ start_node[ path[x] ] ];
        else
            y = tata[ start_node[ path[y] ] ];
    }

    return pos_in_path[x] < pos_in_path[y] ? x : y;
}

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

    in >> N >> Q;

    for ( int i = 2, a; i <= N; ++i )
    {
        in >> a;
        G[a].push_back( i );
    }

    build_hpd();

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

    return 0;
}