<----my github

POJ 1330Nearest Common Ancestors 最近的共同祖先

题目链接在这里

从题目的描述和输入情况可以看出,这是要寻找树中某两个节点的最近的公共祖先,根据题目的特性,我们可以将每个节点的父节点保存在一个数组中,如i的父节点为j可表示为father[i]=j。

这里提供两种算法的思路:
一、这个最近的公共祖先一定是公共祖先,如果它存在那么它一定在两个节点到根节点的路径上。
所以可以求出两个节点到根节点的路径,保存在两个数组里,
然后逆序比较两个数组,直到到了某个节点两个数组的元素不同(相同的是两个数组的共同祖先),那么这个节点的父节点就是最近共同祖先。
二、第二种算法是对第一种算法的改进,首先并不需要完整的找两个根节点到父节点的路径,因为这样的话它们的最近共同祖先到根节点的路径相当于是遍历了两次,没有能够有效利用这段路径的信息,
事实上,我们可以在寻找第一个节点到根节点的路径的过程中,每经过一个节点,就把这个节点的父节点设置为0,即father[i]=0,
这样的话,在寻找第二个节点的过程中,如果到根节点路径上有一个节点的父节点是0,那就说明这个节点就是最近共同祖先,返回这个节点即可。

算法2的参考代码如下:

点击查看代码
#include<iostream>
using namespace std;
int father[10005];
int main() {
	memset(father, 0, 10005 * sizeof(int));
	int testNum,i;
	int totalNum;
	cin >> testNum;
	int fork1, fork2;
	int temp1,temp2;
	while (testNum--)
	{
		cin >> totalNum;
		while ((totalNum--)>1)
		{
			cin >> fork1 >> fork2;
			father[fork2] = fork1;
		}
		cin >> fork1 >> fork2;
		for (temp1 = fork1; temp1 > 0;) {
			temp2 = father[temp1];
			father[temp1] = 0;
			temp1 = temp2;
		}
		temp1 = 0;
		for (temp1 = fork2; temp1 > 0; temp1 = father[temp1]) {
			if (father[temp1] == 0) break;
		}
		cout << temp1<<endl;
	}
}
posted @ 2022-01-02 21:03  CinqueOrigin  阅读(50)  评论(0)    收藏  举报