Pagini recente » Cod sursa (job #1398405) | Cod sursa (job #2725237) | Cod sursa (job #2706804) | Cod sursa (job #411286) | Cod sursa (job #3149028)
#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;
}