Cod sursa(job #1209562)

Utilizator dm1sevenDan Marius dm1seven Data 18 iulie 2014 00:19:00
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.88 kb
#include <iostream>
using namespace std;
#include <fstream>
#include <algorithm>
#include <list>
#include <vector>

namespace e_040_lca_
{
	//depth of each node
	void build_depth(int N, int** parents, int* depths)
	{
		for (int i = 1; i <= N; i++) {
			int d = 0; int p = i;
			while (p != 1) { p = parents[p][1]; d++; }
			depths[i] = d;
		}
	}

	//depth by depth first search
	void dfs(int node, int depth, int N, int* parents, int* depths)
	{
		//assign the depth to the current node
		depths[node] = depth;
		//look for the childs of the current node
		for (int i = 2; i <= N; i++) if (parents[i] == node) dfs(i, depth + 1, N, parents, depths);
	}

	void dfs(int node, int depth, int N, vector<list<int>>& tree, int* depths)
	{
		depths[node] = depth;
		for (auto& child : tree[node]) {
			dfs(child, depth + 1, N, tree, depths);
		}
	}

	void depth_tree(int N, int** parents, int* depths)
	{
		vector<list<int>> tree;
		tree.resize(N+1);

		//create the tree
		for (int i = 2; i <= N; i++) {
			int p = parents[i][1];
			tree[p].push_back(i); //add the child
		}

		dfs(1, 0, N, tree, depths);
	}

	void build_2powk_parents(int N, int** parents)
	{
		int log2_N = (int)ceil(log2(N)) + 1;
		for (int k = 1; k < log2_N; k++)
		{
			for (int i = 2; i <= N; i++) {
				int pk = parents[i][k];
				parents[i][k + 1] = parents[pk][k];
			}
		}
	}	

	int lca_eq_depth(int u, int v, int N, int** parents)
	{
		if (u == 1 || v == 1) return 1;

		int k = 0;
		while (parents[u][k] != parents[v][k]) k++;
		
		if (k <= 2) return parents[u][k];
		//otherwise
		int u1 = parents[u][k-1];
		int v1 = parents[v][k-1];

		return lca_eq_depth(u1, v1, N, parents);
	}

	int lca(int u, int v, int N, int** parents, int* depths)
	{
		if (depths[u] > depths[v]) swap(u, v);
		int d = (depths[v] - depths[u]);
		int e = 1;
		while (d != 0) {
			if (d % 2) v = parents[v][e];
			e++;
			d >>= 1;
		}

		//now u and v have the same depth
		return lca_eq_depth(u, v, N, parents);
	}
}

//int e_040_lca()
int main()
{
	using namespace e_040_lca_;

	int N, M;

	ifstream ifs("lca.in");
	ofstream ofs("lca.out");

	ifs >> N >> M;
	int log2_N = (int)ceil(log2(N)) + 1;
	int** parents = new int*[N + 1];
	for (int i = 0; i <= N; i++) parents[i] = new int[log2_N + 1];
	int* depths = new int[N + 1];
	
	//initializations
	for (int k = 0; k <= log2_N; k++) {
		parents[1][k] = 0; //the root has no parent
		parents[0][k] = 0; //used when building 2^k parents
	}

	parents[1][0] = 1;

	for (int i = 2; i <= N; i++) {
		int p;
		ifs >> p;
		parents[i][0] = i;
		parents[i][1] = p;
	}

	depth_tree(N, parents, depths);
	//dfs(1, 0, N, parents, depths);
	build_2powk_parents(N, parents);

	for (int i = 1; i <= M; i++) {
		int u, v;
		ifs >> u >> v;
		ofs << lca(u, v, N, parents, depths) << "\n";
	}

	ifs.close();
	ofs.close();

	return 0;
}