Cod sursa(job #865761)

Utilizator enedumitruene dumitru enedumitru Data 26 ianuarie 2013 22:29:04
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.13 kb
/* 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;
}