POJ 1330 Nearest Common Ancestors (最近公共祖先)

题目通道:POJ 1330

Describe:
A rooted tree is a well-known data structure in computer science and engineering. An example is shown below:


In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of node y if node x is in the path between the root and node y. For example, node 4 is an ancestor of node 16. Node 10 is also an ancestor of node 16. As a matter of fact, nodes 8, 4, 10, and 16 are the ancestors of node 16. Remember that a node is an ancestor of itself. Nodes 8, 4, 6, and 7 are the ancestors of node 7. A node x is called a common ancestor of two different nodes y and z if node x is an ancestor of node y and an ancestor of node z. Thus, nodes 8 and 4 are the common ancestors of nodes 16 and 7. A node x is called the nearest common ancestor of nodes y and z if x is a common ancestor of y and z and nearest to y and z among their common ancestors. Hence, the nearest common ancestor of nodes 16 and 7 is node 4. Node 4 is nearer to nodes 16 and 7 than node 8 is.

For other examples, the nearest common ancestor of nodes 2 and 3 is node 10, the nearest common ancestor of nodes 6 and 13 is node 8, and the nearest common ancestor of nodes 4 and 12 is node 4. In the last example, if y is an ancestor of z, then the nearest common ancestor of y and z is y.

Write a program that finds the nearest common ancestor of two distinct nodes in a tree.
Input:
The input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case starts with a line containing an integer N , the number of nodes in a tree, 2<=N<=10,000. The nodes are labeled with integers 1, 2,..., N. Each of the next N -1 lines contains a pair of integers that represent an edge --the first integer is the parent node of the second integer. Note that a tree with N nodes has exactly N - 1 edges. The last line of each test case contains two distinct integers whose nearest common ancestor is to be computed.
Output:
Print exactly one line for each test case. The line should contain the integer that is the nearest common ancestor.
Sample Input:
2
16
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
5
2 3
3 4
3 1
1 5
3 5
Sample Output:
4
3

题目大意:

每个样例给n-1对数,每对数表示前一个数是后一个数的父节点,最后给你俩数,让你找最近公共祖先。

解题思路:

按着老师说的思路写,没写出来,而且感觉比较麻烦,百度了一下,有些神犇写的通俗易懂,学到了。根据题目的输入,用双亲法存这棵树是比较方便的,存完之后,假设要找x,y的最短公共祖先,我们可以先把y的所有祖先标记出来,然后再找x的所有祖先,一旦发现第一个被标记的祖先,则该祖先即为最近公共祖先。

AC代码:

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #define N 10010
 5 using namespace std;
 6 int a[N]; // 用来建树
 7 int b[N]; // 用来标记祖先
 8 int main()
 9 {
10     int t,n,x,y; // 各种变量
11     scanf("%d",&t);
12     while(t--)
13     {
14         memset(a,0,sizeof(a)); // 每个样例前一定要先初始化
15         memset(b,0,sizeof(b));
16         scanf("%d",&n);
17         for(int i = 0; i < n-1; i++)
18         {
19             scanf("%d%d",&x,&y);
20             a[y] = x; // 双亲建树过程
21         }
22         scanf("%d%d",&x,&y);
23         while(y != 0) // 标记y的祖先,若y等于0,说明已经找到根节点了
24         {
25             b[y] = 1; // 标记路径, 注意要先标记再找祖先,不然可能会错过根节点
26             y = a[y]; // 找y的祖先
27         }
28         while(b[x] == 0) // 找x的祖先,如果找到了第一个标记的,即为答案
29         {
30             x = a[x];
31         }
32         printf("%d\n",x);
33     }
34     return 0;
35 }

 

小结:

没有小结的小结

 

posted @ 2020-08-09 13:04  不敢说的梦  阅读(139)  评论(0)    收藏  举报