Cod sursa(job #2293513)

Utilizator andrei.seritanAndrei Seritan andrei.seritan Data 1 decembrie 2018 00:50:34
Problema Lowest Common Ancestor Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.54 kb
#include <stdio.h>
#include <vector>

using namespace std;

int min(int x, int y) {
    if (x <= y) {
        return x;
    }
    return y;
}

int find_root(const std::vector<std::vector<int>>& graph, const int num_nodes) {
    int entry_level[num_nodes + 1] = {0};
    for (register int i = 0; i < num_nodes; ++i) {
        for (int son : graph[i]) {
            entry_level[son]++;
        }
    }
    for (register int i = 0; i < num_nodes; ++i) {
        if (entry_level[i] == 0) {
            return i;
        }
    }
    return -1;
}

void compute_euler(const std::vector<std::vector<int>>& graph,\
    std::vector<int> &euler, int *first_appearance,\
    int *node_order, int node, bool *visited, int &counter) {
    if (visited[node] == false) {
        visited[node] = true;
        int node_id = counter;
        node_order[counter++] = node;
        first_appearance[node] = euler.size();
        euler.push_back(node_id);
        for (int son : graph[node]) {
            compute_euler(graph, euler, first_appearance, node_order,\
                son, visited, counter);
            euler.push_back(node_id);
        }
    }
}

void compute_rmq(const std::vector<int>& log, std::vector<std::vector<int> >& rmq,\
    const std::vector<int>& euler, const int size) {

    for (register int i = 0; i < size; ++i) {
        rmq[i][0] = euler[i];
    }
    int power = 2;
    for (register int step = 1; power <= size; ++step, power <<= 1) {
        int put = power >> 1;
        for (register int i = 0; i + put < size; ++i) {
            rmq[i][step] = min(rmq[i][step - 1], rmq[i + put][step - 1]);
        }
    }
}

int query_rmq(const std::vector<int>& log, const std::vector<std::vector<int> >& rmq,\
    int x, int y, int *first_appearance, int *node_order) {
    int l = first_appearance[x];
    int r = first_appearance[y];
    if (r < l) {
        int aux = l;
        l = r;
        r = aux;
    }
    int step = log[r - l + 1];
    return node_order[min(rmq[l][step], rmq[r - (1 << step) + 1][step])];
}

void compute_log(std::vector<int>& log, int size) {
    for (register int i = 1; (1 << i) <= size; ++i) {
        log[1 << i] = 1;
    }
    for (register int i = 1; i <= size ; ++i) {
        log[i] += log[i - 1];
    }
}

std::vector<int> lca(const std::vector<std::vector<int>>& graph, int m, FILE *out, FILE *in) {

    std::vector<int> euler;
    int num_nodes = graph.size() - 1;
    bool visited[num_nodes + 1] = {false};
    int first_appearance[num_nodes + 1] = {0};
    int node_order[num_nodes + 1] = {0};
    int counter = 0;
    int root = 1;

    compute_euler(graph, euler, first_appearance, node_order, root, visited, counter);
    std::vector<int> log(euler.size(), 0);
    compute_log(log, euler.size());
    std::vector<std::vector<int> > rmq(euler.size(), std::vector<int>(log[euler.size()]));

    compute_rmq(log, rmq, euler, euler.size());
    for (register int i = 0; i < m; ++i){
        int x, y;
        fscanf(in, "%d%d", &x, &y);
        int sol = query_rmq(log, rmq, x, y, first_appearance, node_order);
        fprintf(out, "%d\n", sol);
    }
    return std::vector<int>();
}

int main() {
    int n, m;
    FILE *in, *out;
    in = fopen("lca.in", "r");
    out = fopen("lca.out", "w");
    fscanf(in, "%d %d", &n, &m);
    vector< vector<int> > *graph = new vector< vector<int> >(n + 1, vector<int>(0));
    // vector < pair<int, int> > *queries = new vector < pair<int, int> >(0);
    for (register int i = 1; i < n; ++i) {
        int x;
        fscanf(in, "%d", &x);
        graph -> at(x).push_back(i + 1);
    }

    lca(*graph, m, out, in);
    return 0;
}