Cod sursa(job #2608136)

Utilizator cip_ionescuCiprian Ionescu cip_ionescu Data 30 aprilie 2020 17:35:08
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.53 kb
//
//  main.cpp
//  lca
//
//  Created by Ciprian Ionescu on 4/30/20.
//  Copyright © 2020 CIP.FUN. All rights reserved.
//

#include <iostream>
#include <fstream>
#include <vector>
#include <array>
#include <queue>
#include <stack>

#define MAX_N 100000
#define MAX_LOG 18

using std::cin;
using std::cout;

template <typename T, typename C = T>
struct Node {
    T node;
    Node *next;
    C weight;
};

template <typename T, size_t N, size_t M>
class Graph {
public:
    size_t size;
    
    void add(const T& x, const T& y) {
        _nodes[++size].node = y;
        _nodes[size].next = _list[x];
        _list[x] = &_nodes[size];
    }
    
    void add_weighted(const T& x, const T& y, const T& weight) {
        _nodes[++size].node = y;
        _nodes[size].weight = weight;
        _nodes[size].next = _list[x];
        _list[x] = &_nodes[size];
    }
    
    Node<T>& get_node(const T& x) {
        return *_list[x];
    }
    
    bool visited(const T& x) {
        return _visited[x];
    }
    
    void visit(const T& x) {
        _visited[x] = true;
    }
    
    void reset() {
        for (auto &it : _visited) it = false;
    }

private:
    std::array<Node<T>, M> _nodes;
    std::array<Node<T>*, N> _list;
    
    std::array<bool, N> _visited;
};

int ti[1 + MAX_N], to[1 + MAX_N], tm, t[MAX_LOG][1 + MAX_N];

template <typename T, size_t N, size_t M>
void ancestor_tree(Graph<T, N, M>& g, const T& x) {
    g.visit(x);
    ti[x] = ++tm;
    
    Node<T>* p = &g.get_node(x);
    
    while (p) {
        if (!g.visited(p->node)) {
            ancestor_tree(g, p->node);
            t[0][p->node] = x;
        }
        p = p->next;
    }
    
    to[x] = ++tm;
}

int lca(int x, int y) {
    if (ti[x] <= ti[y] && to[y] <= to[x])
        return x;
    
    int step = MAX_LOG - 1;
    while (step >= 0) {
        const int s = t[step][x];
        if (s != 0 && ((ti[s] > ti[y]) || (to[y] > to[s])))
            x = s;
        step--;
    }
    return t[0][x];
}

Graph<int, 1 + MAX_N, 1 + MAX_N> g;

int main(int argc, const char * argv[]) {
    std::ifstream fin("lca.in");
    std::ofstream fout("lca.out");
    
    int n, m;
    fin >> n >> m;
    
    for (auto i = 2 ; i <= n ; i++) {
        int x;
        fin >> x;
        g.add(x, i);
    }
    
    ancestor_tree(g, 1);
    
    for (auto i = 1 ; (1 << i) <= n ; i++) {
        for (auto j = 1 ; j <= n ; j++)
            t[i][j] = t[i - 1][t[i - 1][j]];
    }
    
    for (auto i = 1 ; i <= m ; i++) {
        int x, y;
        fin >> x >> y;
        fout << lca(x, y) << '\n';
    }
    return 0;
}