Cod sursa(job #3149028)

Utilizator AleXutzZuDavid Alex Robert AleXutzZu Data 5 septembrie 2023 18:55:48
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.97 kb
#include <fstream>
#include <vector>
#include <cmath>

#define MAX_SIZE 100000

struct Graph {
private:
    std::vector<std::vector<int>> graph;

public:
    explicit Graph(int nodes) {
        graph.resize(nodes + 1);
    }

    void add_edge(int x, int y) {
        graph[x].push_back(y);
        graph[y].push_back(x);
    }

    const std::vector<int> &operator[](int node) {
        return graph[node];
    }
};

Graph graph(MAX_SIZE);

struct LCA {
private:
    int timer;
    int logN;
    std::vector<int> time_of_entry;
    std::vector<int> time_of_exit;
    std::vector<std::vector<int>> up;

    void dfs(int node, int root) {
        time_of_entry[node] = ++timer;

        up[0][node] = root;

        for (int i = 1; i <= logN; ++i) {
            up[i][node] = up[i - 1][up[i - 1][node]];
        }

        for (const auto &x: graph[node]) {
            if (x == root) continue;
            dfs(x, node);
        }

        time_of_exit[node] = ++timer;
    }

    bool is_ancestor(int x, int y) {
        return time_of_entry[x] <= time_of_entry[y] && time_of_exit[x] >= time_of_exit[y];
    }

public:
    explicit LCA(int nodes) {
        time_of_entry.resize(nodes + 1, 0);
        time_of_exit.resize(nodes + 1, 0);
        timer = 0;
        logN = std::ceil(std::log2(nodes));

        up.resize(logN + 2, std::vector<int>(nodes + 1, 0));

        dfs(1, 1);
    }

    int query(int x, int y) {
        if (is_ancestor(x, y)) return x;
        if (is_ancestor(y, x)) return y;

        for (int i = logN; i >= 0; --i) {
            if (!is_ancestor(up[i][x], y)) x = up[i][x];
        }
        return up[0][x];
    }
};

int main() {
    std::ifstream input("lca.in");
    std::ofstream output("lca.out");
    int n, m;
    input >> n >> m;

    for (int i = 1; i < n; ++i) {
        int x;
        input >> x;
        graph.add_edge(x, i + 1);
    }

    LCA lca(n);
    while (m--) {
        int a, b;
        input >> a >> b;
        output << lca.query(a, b) << '\n';
    }

    return 0;
}