Cod sursa(job #2500868)

Utilizator mihnea00Duican Mihnea mihnea00 Data 28 noiembrie 2019 19:51:58
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.84 kb
#include <iostream>
#include <fstream>
#include <vector>

void mySwap (int &a, int &b) {
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
}

int findParent(int &node, int *parent) {
	if (node != parent[node])
		parent[node] = findParent(parent[node], parent);
	return parent[node];
}

void makeUnion (int &node1, int &node2, int *parent, int *rank) {
	int root1 = findParent(node1, parent);
	int root2 = findParent(node2, parent);

	if (root1 != root2) {
		if (rank[root1] < rank[root2])
			mySwap(root1, root2);

		parent[root2] = root1;
		if (rank[root1] == rank[root2])
			rank[root1]++;
	}
}

void recursiveDfs(int &node, std::vector<std::vector<int>> &graph,
	std::vector< std::vector< std::pair<int, int> > >& queries, bool *visited,
	int *ancestor, int *parent, int *rank, std::vector<int> &answer) {

	parent[node] = node;
	ancestor[node] = node;
	rank[node] = 1;
	visited[node] = 1;

	for (int i = 0; i < graph[node].size(); ++i) {

		if (!visited[graph[node][i]]) {

			recursiveDfs(graph[node][i], graph, queries, visited,
				ancestor, parent, rank, answer);

			makeUnion(node, graph[node][i], parent, rank);
			ancestor[findParent(node, parent)] = node;
		}
	}

	for (int i = 0; i < queries[node].size(); ++i) {
		if (visited[queries[node][i].first] == 1)
			answer[queries[node][i].second] =
		ancestor[findParent(queries[node][i].first, parent)];
	}
	
}

std::vector<int> lca(std::vector<std::vector<int>> &graph,
	std::vector< std::pair<int, int> > &queries) {

	bool *visited;
	int node = 1, *ancestor, *rank, *parent;
	std::vector<int> answer(queries.size(), 0);
	
	std::vector< std::vector< std::pair<int, int> > > eachNodeQuery(graph.size());

	for (int i = 0; i < queries.size(); ++i) {
		eachNodeQuery[queries[i].first].push_back({queries[i].second, i});
		eachNodeQuery[queries[i].second].push_back({queries[i].first, i});

	}

	visited = new bool[graph.size()] {0};
	ancestor = new int[graph.size()] {0};
	parent = new int[graph.size()] {0};
	rank = new int[graph.size()] {1};

	recursiveDfs(node, graph, eachNodeQuery, visited, ancestor, parent, rank, answer);

	delete [] visited;
	delete [] ancestor;
	delete [] rank;
	delete [] parent;

    return answer;
}

int main () {
	std::ifstream fin("lca.in");
	std::ofstream fout("lca.out");

	int n, m, node1, node2;
	std::vector< std::vector<int> > graph;
	std::vector< std::pair<int, int> > queries;


	fin >> n >> m; // number of nodes and queries
	graph.resize(n + 1);

	for (int i = 2; i <= n; ++i) {
        fin >> node1;
        graph[node1].push_back(i);
        graph[i].push_back(node1);

		// fin >> node1 >> node2;
  //       graph[node1].push_back(node2);
  //       graph[node2].push_back(node1);
	}

	for (int i = 0; i < m; ++i) {
        fin >> node1 >> node2;
		queries.push_back({node1, node2});
	}

	std::vector<int> ans = lca(graph, queries);

	for (int i = 0; i < ans.size(); ++i) {
		fout << ans[i] << "\n";
	}

	return 0;
}