Cod sursa(job #1134602)

Utilizator antonioteoZait Teodor Antonio antonioteo Data 6 martie 2014 19:39:57
Problema Lowest Common Ancestor Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 1.68 kb
#include <fstream>
using namespace std;

ifstream fin("lca.in");
ofstream fout("lca.out");

#define NMAX 100001

int i, j, N, M, T;
int X, Y;

int Ancestor[20][NMAX];
int Level[NMAX];
int Log[NMAX];

struct nod {
	int U;
	nod *next;
};
nod *v[NMAX];
bool used[NMAX];

void add(int A, int B) {
	nod *P = new nod;
	P->U = B;
	P->next = v[A];
	v[A] = P;
}

void DFS(int node) {
	used[node] = true;
	for (nod *it = v[node]; it; it = it->next) {
		if (!used[it->U]) {
			Level[it->U] = Level[node] + 1;
			Ancestor[0][it->U] = node;
			DFS(it->U);
		}
	}
}

void BringToLevel(int &X, int L) {
	int cnt, n, k, last;
	n = Level[X] - L;
	last = X;
	for (cnt = 1; cnt <= n; cnt <<= 1);
	for (k = Level[X]; cnt; cnt >>= 1)
		if (k - cnt >= L)
			k -= cnt, last = Ancestor[Log[cnt]][last];
	X = last;
}

int LCA(int X, int Y) {
	int cnt = 0, k, lastX, lastY;
	if (Level[Y] > Level[X]) swap(X, Y);
	if (Level[X] != Level[Y])
		BringToLevel(X, Level[Y]);
	if (X == Y) return X;
	lastX = X;
	lastY = Y;
	for (cnt = 1; cnt <= Level[X]; cnt <<= 1);
	for (k = Level[X]; cnt; cnt >>= 1)
		if (k - cnt >= 1 && Ancestor[Log[cnt]][lastX] != Ancestor[Log[cnt]][lastY])
			k -= cnt, lastX = Ancestor[Log[cnt]][lastX], lastY = Ancestor[Log[cnt]][lastY];
	return Ancestor[0][lastY];
}

int main() {
	fin >> N >> M;
	for (i = 2; i <= N; ++i) Log[i] = Log[(i >> 1)] + 1;
	for (i = 2; i <= N; ++i) {
		fin >> T;
		add(i, T);
		add(T, i);
	}
	DFS(1);
	for (i = 1; (i << 1) <= N; ++i)
		for (j = 2; j <= N; ++j) 
			Ancestor[i][j] = Ancestor[i - 1][ Ancestor[i - 1][j] ];
	for (i = 1; i <= M; ++i) {
		fin >> X >> Y;
		fout << LCA(X, Y) << '\n';
	}
	return 0;
}