Cod sursa(job #2679457)

Utilizator Catalina07Encea Catalina Catalina07 Data 30 noiembrie 2020 16:35:54
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.14 kb
	
#include <iostream>
#include <fstream>
#include <vector>
#include <bits/stdc++.h>

int getAllParents(int &node, int *parent){
	if(node == parent[node]){
		return parent[node];
	}
	else{
		parent[node] = getAllParents(parent[node], parent);
		return parent[node];
	}
}
	void makeUnion (int &node1, int &node2, int *parent, int *rank) {
	int root1 = getAllParents(node1, parent);
	int root2 = getAllParents(node2, parent);
 
	// std::cout << node1 <<"Da\n";
 
	if (root1 != root2) {
		if (rank[root1] < rank[root2]){
			root1 = root1 ^ root2;
			root2 = root1 ^ root2;
			root1 = 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]]) {
			// std::cout << graph[node][i] << "Da\n";
			recursiveDfs(graph[node][i], graph, queries, visited,
				ancestor, parent, rank, answer);
 
			makeUnion(node, graph[node][i], parent, rank);
			ancestor[getAllParents(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[getAllParents(queries[node][i].first, parent)];
	}
	
}
 
std::vector<int> lca(std::vector<std::vector<int>> &graph,
	std::vector< std::pair<int, int> > &queries) {
 
	// std::vector<bool> visited(graph.size());
 
	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});
 
	}
	// std::vector<int> answer;
 
 
	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, parent, 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);
 
 
	// lca_tarjan obj(n);
	for (int i = 2; i <= n; ++i) {
        // fin >> node1 >> node2;
        // obj.addInTree(parent, i);
        fin >> node1;
        graph[node1].push_back(i);
        graph[i].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";
	}
	// std::cout << "\n" << ans.size() << "\n";
 
 
	return 0;
}