Pagini recente » Cod sursa (job #658150) | Cod sursa (job #1890909) | Rating Andrei Gonczi (figure0907) | Cod sursa (job #2234950) | Cod sursa (job #2955976)
#include <bits/stdc++.h>
// #include "dsu.hpp"
class DSU {
private:
std::vector<int> rank, rep;
public:
DSU(int n);
int find_rep(int x);
void unite(int x, int y);
bool check(int x, int y);
};
int DSU::find_rep(int x) {
if (rep[x] == x)
return x;
return rep[x] = find_rep(rep[x]);
}
DSU::DSU(int n) : rank(n + 1), rep(n + 1) {
for (int i = 1; i <= n; ++i)
rep[i] = i;
}
void DSU::unite(int x, int y) {
int rep_x = find_rep(x), rep_y = find_rep(y);
if (rank[rep_x] < rank[rep_y]) {
++rank[rep_y];
rep[rep_x] = rep_y;
} else {
++rank[rep_y];
rep[rep_x] = rep_y;
}
}
bool DSU::check(int x, int y) {
return find_rep(x) == find_rep(y);
}
using namespace std;
vector<int> tarjan_offline(const vector<vector<int>>& tree,
const vector<vector<pair<int, int>>>& queries) {
DSU dsu(tree.size());
vector<bool> visited(tree.size(), false);
vector<int> ancestor(tree.size());
vector<int> ans(transform_reduce(queries.begin(), queries.end(), 0, plus{},
size<decltype(queries[0])>) / 2);
function<void(int)> dfs = [&](int current) {
visited[current] = true;
ancestor[current] = current;
for (int neigh : tree[current])
if (!visited[neigh]) {
dfs(neigh);
dsu.unite(current, neigh);
ancestor[dsu.find_rep(current)] = current;
}
for (auto [other_node, index] : queries[current])
if (visited[other_node]) {
ans[index] = ancestor[dsu.find_rep(other_node)];
}
};
dfs(0);
return ans;
}
int main() {
ifstream fin("lca.in");
ofstream fout("lca.out");
int n, m;
fin >> n >> m;
vector<vector<int>> tree(n);
for (int i = 1, x; i < n; ++i) {
fin >> x;
--x;
tree[i].push_back(x);
tree[x].push_back(i);
}
vector<vector<pair<int, int>>> queries(n);
for (int i = 0, x, y; i < m; ++i) {
fin >> x >> y;
--x;
--y;
queries[x].push_back({y, i});
queries[y].push_back({x, i});
}
for (int x : tarjan_offline(tree, queries)) {
fout << ++x << '\n';
}
}