Cod sursa(job #690427)

Utilizator prisonbreakMichael Scofield prisonbreak Data 25 februarie 2012 16:53:48
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.17 kb
#include <cstdio>
#include <vector>


const int maxn = 100010;
using namespace std;

vector <int> G[maxn];
int T[18][maxn], lev[maxn];

void DF(int node, int l) {	
	lev[node] = l;
	for( vector <int> :: iterator it = G[node].begin(); it != G[node].end(); ++it )
		DF(*it, l + 1);
}
int lca(int x, int y) {
	
	if(lev[x] < lev[y]) swap(x, y);
	
	int log1 = 1, log2 = 1;

	for(; (1 << log1) < lev[x]; ++log1 ) ;
	for(; (1 << log2) < lev[y]; ++log2 ) ; 
	
	for(int k = log1; k >= 0; --k )
		if(lev[x] - (1 << k) >= lev[y])
			x = T[k][x];
	
	if(x == y) return x;
	
	for(int k = log2; k >= 0; --k )
		if(T[k][x] && T[k][x] != T[k][y]) {
			x = T[k][x];
			y = T[k][y];
		}
	return T[0][x];
}	
int main() {

	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);

	int N, M;
	scanf("%d%d\n", &N, &M);

	for( int i = 2; i <= N; ++i ) {
		scanf("%d", &T[0][i]);
		G[ T[0][i] ].push_back(i);
	}
	for( int j = 1; (1 << j) <= N; ++j ) {
		for( int i = 1; i <= N; ++i) {
			T[j][i] = T[j - 1][ T[j - 1][i] ];
		//	printf("%d ", T[j][i]);
		}
		//printf("\n");
	}
	DF(1, 0);
	
//	printf("\n");
	for( ; M-- ; ) {
		int x, y;
		scanf("%d %d\n", &x, &y);
		printf("%d\n", lca(x, y));
	}
	return 0;
}