Pagini recente » Cod sursa (job #837839) | Cod sursa (job #2011842) | Cod sursa (job #1190128) | Cod sursa (job #2217403) | Cod sursa (job #1209550)
#include <iostream>
using namespace std;
#include <fstream>
#include <algorithm>
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;
}
}
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;
}
build_depth(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;
}