Pagini recente » Cod sursa (job #707042) | Cod sursa (job #247482) | Cod sursa (job #148031) | Cod sursa (job #1133030) | Cod sursa (job #2498853)
#include <bits/stdc++.h>
#define N 100000
#define LMAX 100 // computed as ceil(log(N))
void eulerTour(const std::vector<std::vector<int>>& graph, int currentNode, std::vector<bool>& visited,
std::vector<int>& tour, std::vector<int>& depth, std::vector<int>& firstOccurence, int level) {
visited[currentNode] = true;
depth[currentNode] = level;
if(firstOccurence[currentNode] == -1) {
firstOccurence[currentNode] = tour.size();
}
tour.push_back(currentNode);
for(int i = 0; i < graph[currentNode].size(); ++i) {
if(!visited[graph[currentNode][i]]) {
eulerTour(graph, graph[currentNode][i], visited, tour, depth, firstOccurence, level + 1);
tour.push_back(currentNode);
}
}
}
std::vector<int> lca(const std::vector<std::vector<int>>& graph, const std::vector< std::pair<int, int> >& queries) {
std::vector<bool> visited(graph.size(), false);
std::vector<int> euler(1,0), depth(graph.size()), firstOcurrence(graph.size(), -1), eulerLevels;
std::vector<int> res;
eulerTour(graph, 1, visited, euler, depth, firstOcurrence, 1);
for(auto r : euler) {
eulerLevels.push_back(depth[r]);
}
std::vector<std::vector<int>> rmq(LMAX);
for(auto& v:rmq) {
v.resize(eulerLevels.size() + 1);
}
std::vector<int> lg(eulerLevels.size() + 1, 0);
int n = eulerLevels.size();
for (int i = 2; i <= n; i++) {
lg[i] = lg[i/2] + 1;
}
for (int i = 1; i <= n; i++) {
rmq[0][i] = i;
}
for (int i = 1; (1 << i) < n; i++) {
for (int j=1; j <= n - (1 << i); j++) {
int l = 1 << (i-1);
if(eulerLevels[rmq[i-1][j]] < eulerLevels[rmq[i-1][j+l]]) {
rmq[i][j] = rmq[i-1][j];
} else {
rmq[i][j] = rmq[i-1][j+l];
}
}
}
for(auto& query: queries) {
int firstNode = firstOcurrence[query.first], secondNode = firstOcurrence[query.second];
if(firstNode > secondNode ) {
std::swap(firstNode, secondNode);
}
int diff = secondNode - firstNode + 1;
int level = lg[diff];
int sh = diff - (1 << level);
if(eulerLevels[rmq[level][firstNode]] < eulerLevels[rmq[level][firstNode+sh]]) {
res.push_back(euler[rmq[level][firstNode]]);
} else {
res.push_back(euler[rmq[level][firstNode+sh]]);
}
}
return res;
}
void addEdge(int a,int b, std::vector<std::vector<int>>& graph)
{
graph[a].push_back(b);
graph[b].push_back(a);
}
int main()
{
std::ifstream inputStream;
std::ofstream outputStream;
int n, m;
inputStream.open("lca.in");
inputStream>>n>>m;
std::vector<std::vector<int>> graph(n + 5);
std::vector< std::pair<int, int> > queries;
int src, dest;
for(int i = 1; i < n ; ++i) {
inputStream>>dest;
addEdge(dest, i +1, graph);
}
int u , v;
for(int i = 0; i < m; ++i) {
inputStream>>u>>v;
queries.push_back(std::make_pair(u, v));
}
std::vector<int> res = lca(graph, queries);
outputStream.open("lca.out");
for(auto& r:res) {
outputStream<<r<<'\n';
}
outputStream.close();
inputStream.close();
return 0;
}