Pagini recente » Cod sursa (job #458462) | Cod sursa (job #57524) | Cod sursa (job #2607358) | Cod sursa (job #1266434) | Cod sursa (job #3240155)
#include <fstream>
#include <vector>
using namespace std;
const int MAX_N = 100005;
const int MAX_L = 20;
ifstream fin("lca.in");
ofstream fout("lca.out");
int N, M;
int T[MAX_L][MAX_N]; // T[k][i] este al 2^k-lea strămoș al lui i
int Lg[MAX_N]; // Lg[i] este log2(i)
int Lev[MAX_N]; // Nivelul fiecărui nod în arbore
vector<int> G[MAX_N]; // Lista de adiacență pentru arbore
void citire() {
fin >> N >> M;
// Citim arborele, unde T[0][i] este părintele lui i
for (int i = 2; i <= N; ++i) {
fin >> T[0][i];
G[T[0][i]].push_back(i);
}
// Precalculăm toți strămoșii folosind DP (Dynamic Programming)
for (int k = 1; (1 << k) <= N; ++k) {
for (int i = 1; i <= N; ++i) {
T[k][i] = T[k - 1][T[k - 1][i]];
}
}
}
void dfs(int nod, int lev) {
Lev[nod] = lev;
// Explorăm copiii nodului curent
for (auto& vecin : G[nod]) {
dfs(vecin, lev + 1);
}
}
int lca(int x, int y) {
if (Lev[x] < Lev[y]) {
swap(x, y); // Ne asigurăm că x este cel mai adânc
}
// Ridicăm nodul x la același nivel cu y
int log1 = 0;
while ((1 << (log1 + 1)) <= Lev[x]) {
log1++;
}
for (int k = log1; k >= 0; --k) {
if (Lev[x] - (1 << k) >= Lev[y]) {
x = T[k][x];
}
}
if (x == y) {
return x; // Dacă am ajuns la același nod, acesta este LCA
}
// Căutăm LCA urcând ambii părinți
for (int k = log1; k >= 0; --k) {
if (T[k][x] && T[k][x] != T[k][y]) {
x = T[k][x];
y = T[k][y];
}
}
return T[0][x]; // Părintele comun al lui x și y
}
int main() {
citire();
dfs(1, 0); // Pornim DFS de la rădăcina arborelui, presupusă a fi nodul 1
while (M--) {
int x, y;
fin >> x >> y;
fout << lca(x, y) << "\n";
}
return 0;
}