The nearest common ancestor problem (LCA) of multitree

Task: design an algorithm to return the nearest common ancestor of two nodes in a given tree

Input: Line 1 has a positive integer n, indicating that the given tree has n nodes. The vertex with node No. 1,2,3,...,n and No. 1 is the root of the tree. Next, i n line n, line i+1 describes the son of node I. The first positive integer k in each row indicates that the node has k sons, and then each number of K represents the number of its son nodes. When k=0, it means that this node is a leaf node.

The n+2 line of the input is a positive integer m, indicating the M node pairs of the nearest common ancestor to be calculated. In the next M line, there are two positive integers in each line, the first two are node numbers, and the third is their nearest common ancestor node numbers.

 

Input example:

12

3 2 3 4

2 5 6

0

0

2 7 8

2 9 10

0

0

0

2 11 12

0

0

5

3 11

7 12

4 8

9 12

8 10

Output example:

3 11 1

7 12 2

4 8 1

9 12 6

8 10 2

 

It won't be any advanced algorithm. It's a direct brute force search. In fact, it can also be slightly optimized, that is, only one path needs to be stored, and then another node can be traced all the time, so it's better to compare and judge. But when I think of this, I have finished writing it, and I have no idea to change it

   

#include <iostream>
#include <vector>
using namespace std;

typedef struct{
	int parent;
	int *son;
}TreeNode;

void findPath(TreeNode* node, int x, vector<int>& path)
{
	int i;
	//	Find the path from this node to the root node
	//	Since the parent node of the root node has been marked as 0, this is the end condition of the loop 
	while( node[x].parent != 0 ){
		i = node[x].parent;
		path.push_back(i);
		x = i;	
	}
}

int find_ClosetParent(vector<int>& path_a, vector<int>& path_b)
{
//	O( path_a.size() * path_b.size() ) 
	for(int i = 0; i < path_a.size(); ++i)
		for(int k = 0; k < path_b.size(); ++k)
			if( path_a[i] == path_b[k] )
				return path_a[i];
				
	return -1;	//	If one of the node pairs is a root node, it cannot be found	
} 

int main()
{	
	int n, m, k, pos;
	while( cin >> n )
	{
		TreeNode node[n+1];
		//	Building tree 
		node[1].parent = 0;	//The parent subscript of the root node is 0 
		for(int i = 1; i <= n; ++i){
//			cout << "node " << i << endl;
			cin >> k;
			node[i].son = (k!=0) ? (new int[k]):nullptr;	//Zero for m means no son 
			for(int j = 0; j < k; ++j){
				cin >> pos;
				node[pos].parent = i;	//Mark the parent of the child node as the current node	
				node[i].son[j] = pos;	//Store the child node subscript of the node 
			}
		}
		//	Looking for common ancestor nodes
		int a, b, res;
		cin >> m;
		while( m-- ){
//			cout << "opt " << endl;
			vector<int> path_a, path_b;
			cin >> a >> b;
			//	Accelerated optimization 
			if( a==b || node[a].parent==node[b].parent ){
				res = node[a].parent;
			}else{
				findPath(node, a, path_a);
				findPath(node, b, path_b);
				res = find_ClosetParent(path_a, path_b);
			}
			cout << a << " " << b << " " << res << endl;
		}
		//	Free the space of son array opened by node array
		for(int i = 1; i <= n; ++i)
			delete[] node[i].son; 
		cout << "-----END-----" << endl;	
	}
	
	return 0;
}

 

Posted by danzene on Fri, 03 Jan 2020 00:14:27 -0800