Pagini recente » Cod sursa (job #1552415) | Cod sursa (job #1951206) | Cod sursa (job #1998602) | Cod sursa (job #2866374) | Cod sursa (job #865761)
Cod sursa(job #865761)
/* 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;
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
void citire ()
{ scanf("%d%d",&n,&m);
for (int x,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=g[nod].begin(), sf=g[nod].end();
for (; it!=sf; 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);
citire();
k=0;
DFS(1,0);
RMQ();
for (int x,y,i=1; i<=m; i++)
{ scanf("%d%d",&x,&y); //nodurile interogate
printf("%d\n",LCA(x,y));
}
return 0;
}