Pagini recente » Cod sursa (job #2780171) | Cod sursa (job #62896) | Cod sursa (job #1415421) | Cod sursa (job #837913) | Cod sursa (job #2134225)
/* LCA(Lowest Common Ancestor): Implemantare utilizand RMQ
Complexitate: O(NlogN+M)
*/
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
#define max_n 100005 //nr de noduri din arbore
#define max_l 20 //logaritmul utilizat in subalgoritmul RMQ
int n,m,k,x,y;
int niv[max_n << 1]; //nivelul nodurilor din reprezentarea EULERIANA
int E[max_n << 1]; //nodurile din parcurgerea EULER
int ap[max_n]; //prima aparitie a fiecarui nod in reprezentare
int Lg[max_n << 1],Rmq[max_l][max_n << 2];
vector <int> g[max_n]; // nodurile din arbore
vector <int>::iterator it;
void citire () {
for (int i=2; i<=n; ++i) {
scanf("%d",&x);
g[x].push_back(i);
}
}
void DFS(int nod,int nivel) { //Parcurgere EULER(de tipul stivei): se parcurg fii si se intercaleaza intre ei tatal
E[++k]=nod;
niv[k]=nivel; // se adauga nodul in vectorul E si se modifica nivelul si aparitia nodului
ap[nod]=k;
vector <int>::iterator it;
for (it=g[nod].begin(); it!=g[nod].end(); it++) {
DFS(*it, nivel+1);
E[++k]=nod;
niv[k]=nivel;
}
}
void RMQ()
{
for(int i=2; i<=k; ++i)
Lg[i]=Lg[i >> 1]+1;
for(int i=1; i<=k; ++i)
Rmq[0][i]=i;
for(int i=1; (1 << i)<k; ++i)
for(int j=1; j<=k-(1 << i); ++j)
{
int l=1 << (i - 1);
Rmq[i][j]=Rmq[i-1][j];
if(niv[Rmq[i-1][j + l]]<niv[Rmq[i][j]])
Rmq[i][j]=Rmq[i-1][j + l];
}
}
int LCA(int x, int y) {
/*Stramosul comun cel mai apropiat (LCA) este nodul de nivel minim dintre primele aparitii ale nodurilor interogate,
x si y, in reprezentarea Euler a arborelui
*/
int a,b,dif,q,l,sol;
a=ap[x]; b=ap[y]; //aparitiile nodurilor x,y;
if (a>b) swap(a,b);
dif=b-a+1;
l=Lg[dif];
sol=Rmq[l][a];
q=dif-(1 << l);
if(niv[sol]>niv[Rmq[l][a+q]]) // se determina minimul intre 2 pozitiile ale sirului niv[] si se returneaza nodul corespunzator
sol=Rmq[l][a+q];
return E[sol];
}
int main () {
freopen("lca.in","r",stdin);
freopen("lca.out","w",stdout);
scanf("%d%d",&n,&m);
citire();
k=0;
DFS(1,0);
RMQ();
for (int i=1; i<=m; i++) {
scanf("%d%d",&x,&y); //nodurile interogate
printf("%d\n",LCA(x,y));
}
return 0;
}