Cod sursa(job #1210512)

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

namespace e_040_lca_
{
	void build_tree(int N, int* parents, vector<list<int>>& tree)
	{
		tree.resize(N + 1);

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

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

	void build_rmq_data(int N, int* v, vector<vector<int>>& ids_min)
	{
		ids_min.resize(N + 1);
		for (int i = 1; i < N; i++)  {
			ids_min[i].resize((int)log2(N - i) + 1);
			ids_min[i][0] = v[i] <= v[i + 1] ? i : i + 1;
		}

		int logN = (int) log2(N);
		for (int k = 1; k <= logN; k++)	{			
			int km1 = k - 1, two_km1 = (1 << km1), two_k = two_km1 << 1;
			for (int i = 1; i <= N - two_k; i++) {
				int id_min1 = ids_min[i][km1]; 
				int id_min2 = ids_min[i + two_km1][km1];
				ids_min[i][k] = v[id_min1] <= v[id_min2] ? id_min1 : id_min2;
			}
		}
	}

	int rmq(int x, int y, int* v, vector<vector<int>>& ids_min)
	{
		if (x == y) return x;
		
		int k = (int)log2(y - x);
		int id_min1 = ids_min[x][k];
		int id_min2 = ids_min[y - (1 << k)][k];

		return v[id_min1] <= v[id_min2] ? id_min1 : id_min2;
	}

	int lca(int u, int v, int* er, int* depths_er, int* er_fpos, vector<vector<int>>& ids_min)
	{
		if (u == v) return u;		

		//who appears first and who second
		if (er_fpos[u] > er_fpos[v]) swap(u, v); //ensure u is the first and v the second

		int id_min = rmq(er_fpos[u], er_fpos[v], depths_er, ids_min);

		return er[id_min];		
	}
}
	
//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* parents = new int[N + 1];
	int* depths = new int[N + 1];

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

	vector<list<int>> tree;
	build_tree(N, parents, tree);

	//count the number of childs
	int no_ch = 0;
	for (int i = 1; i <= N; i++) {
		no_ch += tree[i].size();
	}

	//euler representation
	int* er = new int[no_ch + N + 1];
	int* depths_er = new int[no_ch + N + 1];
	int* er_fpos = new int[N + 1];

	vector<vector<int>> er_pos;
	er_pos.resize(N + 1);

	int eid = 1;
	dfs_euler_depth(1, 0, N, tree, eid, er, er_fpos, depths);
	for (int i = 1; i <= no_ch + N; i++) depths_er[i] = depths[er[i]];

	vector<vector<int>> ids_min;
	build_rmq_data(no_ch + N, depths_er, ids_min);
	
	for (int i = 1; i <= M; i++) {
		int u, v;
		ifs >> u >> v;
		ofs << lca(u, v, er, depths_er, er_fpos, ids_min) << "\n";
	}

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

	delete[] parents; delete[] depths; delete[] er;

	return 0;
}