Cod sursa(job #2499944)

Utilizator mihnea00Duican Mihnea mihnea00 Data 26 noiembrie 2019 23:36:07
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.2 kb
#include <iostream>
#include <fstream>
#include <vector>

// class lca_tarjan {

// 	std::vector< std::vector<int> > children;
// 	std::vector< pair< int, int> > query;
// 	bool *vis;
// 	int *ancestor;

// public:
// 	lca_tarjan();

// 	lca_tarjan(const int &n) {
// 		children.resize(n + 1);
// 		// squery.resize(m);
// 		vis = new bool[n + 1];
// 		ancestor = new int[n+ 1];
// 	}

// 	void addInTree(const int &father, const int &child) {
//         children[father].push_back(child);
// 	}

// 	~lca_tarjan() {
// 		delete vis;
// 		delete ancestor;
// 	}

// 	int findParent(const int &nod) {

// 		if (nod != parent[nod]) {
// 			parent[nod] = findParent(parent[nod]);
// 		}
// 		return parent[nod];
// 	}

// 	void makeDisjointUnion(const int &node1, const int &node2) {
		
// 	}

//     void dfsTarjan(const int &nod) {
//         vis[nod] = 1;
//         ancestor[nod] = nod;
//         for (int i = 0; i < children[nod].size(); ++i) {

//         	dfsTarjan(children[nod][i]);
        	
//         }
//     }

//     void solve() {

//     }

// };

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);

	// std::cout << node1 <<"Da\n";

	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]]) {
			// 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[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) {

	// 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);

	// std::cout << "\n";

	// for (int i = 0; i < graph.size(); ++i) {
	// 	std::cout << ancestor[i] << " ";
	// }
	// std::cout << "\n";


    // TODO

	// std::cout << queries.size() << "\n";


	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;
}