Pagini recente » Cod sursa (job #1173959) | Cod sursa (job #2541388) | Cod sursa (job #1597654) | Cod sursa (job #1932774) | Cod sursa (job #3305363)
#include <bits/stdc++.h>
std::ifstream fin("lca.in");
std::ofstream fout("lca.out");
//#define fin std::cin
//#define fout std::cout
/*
LCA - Tarjan's offline LCA
--------------
-> Fac un DFS in care ma folosesc de DSU pentru a gasi raspunsuri pe subarbori
-> Algoritmul este offline, deci trebuie sa stiu toate query-urile memorate inainte de rulare
*/
const int nmax = 1e5 + 5;
const int qmax = 2e6 + 5;
int n, q;
std::vector<int> graph[nmax];
int father[nmax]; // pentru DSU
int ancestor[nmax]; // ancestor[i] = care este cel mai de sus stramos al componentei lui x
int visited[nmax];
std::vector<std::pair<int, int>> queries[nmax]; // query[x] = {(v, idx) | exista query (x, y) fiind al idx-lea query}
int query_answer[qmax];
int Find(int x)
{
if(father[x] != x)
father[x] = Find(father[x]);
return father[x];
}
void Union(int x, int y)
{
int father_x = Find(x);
int father_y = Find(y);
father[father_y] = father_x;
}
void dfs(int node)
{
father[node] = node;
ancestor[node] = node;
visited[node] = true;
for(int adj : graph[node])
if(!visited[adj])
{
dfs(adj); // merg recursiv in subarbore
Union(node, adj); // unesc surbarborele lui adj la node
//ancestor[Find(node)] = node; // LCA(x, y), unde x si y sub din subarborele cu radacina node
}
for(auto pair : queries[node]) // pot raspunde la queries (x, node) daca am vizitat si nodul x
{
int adj = pair.first;
int idx = pair.second;
if(visited[adj]) // ancestor[Find(adj)] este LCA-ul, radacina subtree-ului cel mai adanc
query_answer[idx] = ancestor[Find(adj)]; // ce contine ambele noduri
}
}
int main()
{
fin >> n >> q;
for(int i = 2; i <= n; ++i)
{
int x;
fin >> x;
graph[i].push_back(x);
graph[x].push_back(i);
}
for(int i = 1; i <= q; ++i)
{
int x, y;
fin >> x >> y;
queries[x].push_back({y, i});
queries[y].push_back({x, i});
}
int root = 1;
dfs(root);
for(int i = 1; i <= q; ++i)
fout << query_answer[i] << "\n";
return 0;
}