Pagini recente » Cod sursa (job #1422273) | Cod sursa (job #2606573) | Cod sursa (job #3279333) | Cod sursa (job #588308) | Cod sursa (job #3235297)
//Se dă un arbore cu rădăcină T. Cel mai apropiat strămoş comun a două noduri u şi v este nodul w care este
// strămoş al ambelor noduri u şi v şi are cea mai mare adâncime în T.
//
//Considerăm că arborele T are n noduri şi are rădăcina în nodul 1. Dându-se o mulţime arbitrară P = {{u,v}},
// cu m perechi neordonate de noduri din T, se cere să se determine cel mai apropiat strămoş al fiecărei perechi din P.
//
//
#include<fstream>
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
const int nmax = 100001;
const int lmax = 20;
int k, n, m;
int nivel[nmax << 1], euler[nmax << 1],prima_apar[nmax];
int rmq[nmax][lmax];
vector<int> g[nmax];
ifstream fin("lca.in");
ofstream fout("lca.out");
void parcurgere(int nod, int niv_curent) //trece prin arbore si creeaza reprezentarea euler
{
k++;
euler[k] = nod;
nivel[k] = niv_curent ;
prima_apar[nod] = k;
for (auto it: g[nod])
{
parcurgere(it, niv_curent +1);
k++;
euler[k] = nod;
nivel[k] = niv_curent ;
}
}
void preprocesare(int n)
{
for(int i = 0; i < n; i++)
rmq[i][0] = nivel[i];
for(int j = 1; (1 << j) <= n; j++)
for(int i = 0; i + (1 << j) - 1 < n; i++)
rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
}
void preprocesare1(int n) {
for (int i = 0; i <= k; i++)
rmq[i][0] = i;
for (int j = 1; (1 << j) <= k + 1; j++)
for (int i = 0; i + (1 << j) - 1 <= k; i++) {
if (nivel[rmq[i][j - 1]] < nivel[rmq[i + (1 << (j - 1))][j - 1]])
rmq[i][j] = rmq[i][j - 1];
else
rmq[i][j] = rmq[i + (1 << (j - 1))][j - 1];
}
}
int query(int nod1, int nod2)
{
int x = prima_apar[nod1], y = prima_apar[nod2];
int k = log2(y - x + 1);
if (rmq[x][k] < rmq[y - (1 << k) + 1][k])
return euler[x];
else
return euler[y - (1 << k) + 1]; //ceva aici nu da bine
//return min(rmq[x][k], rmq[y - (1 << k) + 1][k]); //trb sa punem poz
}
int query1(int nod1, int nod2) {
int x = prima_apar[nod1], y = prima_apar[nod2];
if (x > y) swap(x, y);
int length = y - x + 1;
int k = log2(length);
if (nivel[rmq[x][k]] < nivel[rmq[y - (1 << k) + 1][k]])
return euler[rmq[x][k]];
else
return euler[rmq[y - (1 << k) + 1][k]];
}
int main()
{
int x, a, b;
fin >> n >> m;
//1 1 2 2 2 4 4 6 3 3
for (int i = 2; i <= n; i++) {
fin >> x;
g[x].push_back(i); //se pun copiii
}
k = -1;
parcurgere(1, 0);
/*for (int i = 0; i <= k; i++)
cout<<euler[i]<<" ";
cout<<"\n";
for (int i = 0; i <= k; i++)
cout<<nivel[i]<<" ";
cout<<"\n";*/
preprocesare1(k);
for(int i=0;i<m;i++){
fin>>a>>b;
fout<<query1(a,b)<<endl;
}
return 0;
}