Pagini recente » Cod sursa (job #235950) | Cod sursa (job #2684403) | Cod sursa (job #242630) | Cod sursa (job #2697018) | Cod sursa (job #2529950)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
const int MAXN = 1e5 + 1;
using namespace std;
ifstream in("lca.in");
ofstream out("lca.out");
vector<int>graf[MAXN];/// retine graful de la radacina spre frunze
vector<int>lant[MAXN];
int tata[MAXN],nod_lant[MAXN],nr_lanturi;
bool viz[MAXN];
int n,dimensiune[MAXN],inaltime_lant[MAXN];
int pozitie_lant[MAXN];
void dfs(int nod){
dimensiune[nod] = 1;
viz[nod] = true;
int curent;
for(int i = 0; i < graf[nod].size(); i++){
curent = graf[nod][i];
if(!viz[curent]){
dfs(curent);
dimensiune[nod] += dimensiune[curent];
}
}
if(graf[nod].size() == 0){
/// este frunza
lant[++nr_lanturi].push_back(nod);
pozitie_lant[nod] = 0;/// in vectorul de lant se afla pe pozitia 0,prima pozitie
nod_lant[nod] = nr_lanturi;
}else{
/// are toti vecinii vitati
int vecin_bun;
int maxim = 0;
for(int i = 0; i < graf[nod].size(); i++){
int vecin = graf[nod][i];
if(dimensiune[vecin] > maxim){
maxim = dimensiune[vecin];
vecin_bun = vecin;
}
}
/// am gasit vecinul cu subarborele maxim
int unde = nod_lant[vecin_bun];
lant[unde].push_back(nod);
pozitie_lant[nod] = lant[unde].size() - 1;/// in vectorul lant nod se afla pe ultima pozitie.
nod_lant[nod] = unde;
}
}
void dfs_inaltime_lant(int nod){
viz[nod] = true;
int unde_nod = nod_lant[nod];
for(int i = 0; i < graf[nod].size(); i++){
int curent = graf[nod][i];
int unde_curent = nod_lant[curent];
if(!viz[curent]){
if(unde_curent != unde_nod){
inaltime_lant[unde_curent] = inaltime_lant[unde_nod] + 1;
///cout<<curent<<" "<<nod<<" "<<inaltime_lant[unde_curent]<<" "<<unde_curent<<endl;
}
dfs_inaltime_lant(curent);
}
}
}
void lca(int a,int b){
int index_lant_a = nod_lant[a];
int index_lant_b = nod_lant[b];
/// vreau a > b
if(inaltime_lant[index_lant_a] < inaltime_lant[index_lant_b]){
swap(a,b);
swap(index_lant_a,index_lant_b);
}
while(inaltime_lant[index_lant_a] > inaltime_lant[index_lant_b]){
/// urc a pe lant
int ultim_nod = lant[index_lant_a].back();
a = tata[ultim_nod];
index_lant_a = nod_lant[a];
}
while(nod_lant[a] != nod_lant[b]){
int ultim_nod = lant[index_lant_a].back();
a = tata[ultim_nod];
index_lant_a = nod_lant[a];
ultim_nod = lant[index_lant_b].back();
b = tata[ultim_nod];
index_lant_b = nod_lant[b];
}
/// sunt in acelasi lant => urc folosind pozitie_lant[]
/// pozitiile in lant vin de jos in sus.
/// pozitia 0 inseamna cel mai de jos, pozitia size() - 1 inseamna cel mai de sus
/// eu vreau ca a sa fie mai jos ca b => poz[a] < poz[b]
/// daca nu e asa dau swap
//cout<<a<<" "<<b<<endl;
//cout<<pozitie_lant[a]<<" "<<pozitie_lant[b]<<endl;
if(pozitie_lant[a] > pozitie_lant[b])
swap(a,b);
while(pozitie_lant[a] < pozitie_lant[b]){
a = tata[a];
}
out<<a<<"\n";
}
int main()
{
int intrebari;
in>>n>>intrebari;
for(int i = 1; i <= n - 1; i++){
in>>tata[i + 1];
graf[tata[i + 1]].push_back(i + 1);
///cout<<tata[i + 1]<<" merge in "<<i + 1<<endl;
}
dfs(1);
inaltime_lant[1] = 1;
for(int i = 1; i <= n; i++)
viz[i] = false;
dfs_inaltime_lant(1);
// cout<<endl;
// for(int i = 1; i <= nr_lanturi; i++){
// for(int j = 0; j < lant[i].size(); j++){
// int curent = lant[i][j];
// cout<<curent<<" ";
// if(j + 1 == lant[i].size())
// cout<<"Inaltime : "<<inaltime_lant[i];
// }
// cout<<endl;
// }
for(int i = 1; i <= intrebari; i++){
int a,b;
in>>a>>b;
lca(a,b);
}
return 0;
}