Cod sursa(job #1519026)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 6 noiembrie 2015 18:42:42
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.39 kb
#include <bits/stdc++.h>

using namespace std;

const int MAX_BUFFER = 1 << 16;

int position = MAX_BUFFER;
char buffer[MAX_BUFFER];

char getChar()
{
    if (position == MAX_BUFFER)
    {
        fread(buffer, MAX_BUFFER, 1, stdin);
        position = 0;
    }

    return buffer[ position++ ];
}

int getInt()
{
    int a = 0;
    char c;

    do
    {
        c = getChar();

    } while (!isdigit(c));

    do
    {
        a = a * 10 + c - '0';
        c = getChar();

    } while (isdigit(c));

    return a;
}

const int MAX_N = 100000 + 1;
const int MAX_LG = 16 + 1;
const int NIL = -1;

struct Edge
{
    int v;
    int urm;
};

Edge G[MAX_N];
int head[MAX_N];
int contor = 0;

int father[MAX_N], depth[MAX_N], size[MAX_N];
int posInPath[MAX_N], path[MAX_N], lengthPath[MAX_N], startNode[MAX_N];

int N, Q;
int numberOfPaths;

void addEdge(int x, int y)
{
    G[contor] = {y, head[x]};
    head[x] = contor++;
}

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

    for (int p = head[node]; p != NIL; p = G[p].urm)
    {
        int v = G[p].v;

        if (father[v] == 0)
        {
            father[v] = node;
            depth[v] = depth[node] + 1;

            dfs(v);

            size[node] += size[v];

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

    if (hson == 0)
        path[node] = numberOfPaths++;
    else
        path[node] = path[hson];

    posInPath[node] = lengthPath[ path[node] ]++;
}

void build_heavy()
{
    father[1] = 1;
    depth[1] = 1;
    dfs(1);

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

        if (posInPath[i] == 0)
            startNode[ path[i] ] = i;
    }
}

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

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

int main()
{
    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);

    N = getInt(); Q = getInt();

    for (int i = 1; i <= N; ++i)
        head[i] = NIL;

    for (int i = 2; i <= N; ++i)
    {
        int t = getInt();

        addEdge(t, i);
    }

    build_heavy();

    while (Q--)
    {
        int x, y;
        x = getInt(); y = getInt();
        printf("%d\n", lca(x, y));
    }

    return 0;
}