Cod sursa(job #1977511)

Utilizator andreipasnicuPas Andrei-Nicu andreipasnicu Data 5 mai 2017 13:17:39
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.59 kb
#include <bits/stdc++.h>

using namespace std;

struct LCASolver {
	vector<vector<int>> G;
	vector<int> Jump, SubSize, Depth, Parent;
	bool processed;

	LCASolver(size_t n) : 
		G(n), Jump(n), SubSize(n), Depth(n), Parent(n) {}

	void AddEdge(int a, int b) {
		G[a].push_back(b);
		G[b].push_back(a);
	}

	void Preprocess() {
		DFSSub(0, -1);
		DFSJump(0, 0);

		processed = true;
		G.clear(); G.shrink_to_fit();
		SubSize.clear(); SubSize.shrink_to_fit();
	}

	int GetLCA(int a, int b) {
		assert(processed);

		while (Jump[a] != Jump[b]) {
			if (Depth[Jump[a]] > Depth[Jump[b]])
				a = Parent[Jump[a]];
			else 
				b = Parent[Jump[b]];
		}

		return Depth[a] > Depth[b] ? b : a;
	}

  private:
	
	int DFSSub(int node, int par) {
		SubSize[node] = 1;
		Parent[node] = par;

		if (par != -1) {
			G[node].erase(find(G[node].begin(), G[node].end(), par));
			Depth[node] = 1 + Depth[par];
		}

		for (auto vec : G[node])
			SubSize[node] += DFSSub(vec, node);
	
		return SubSize[node];
	}

	void DFSJump(int node, int jump) {
		Jump[node] = jump;

		int heavy = *max_element(G[node].begin(), G[node].end(), [this](int a, int b) {
			return SubSize[a] < SubSize[b];
		});
		for (auto vec : G[node])
			DFSJump(vec, vec == heavy ? jump : vec);
	}
};

int main() {
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	int n, m, p;
	cin >> n >> m;
	LCASolver lca(n);

	for (int i = 1; i < n; ++i) {
		cin >> p;
		lca.AddEdge(p - 1, i);
	}

	lca.Preprocess();

	while (m--) {
		int a, b;
		cin >> a >> b;
		cout << 1 + lca.GetLCA(a - 1, b - 1) << '\n';
	}
	return 0;
}