POJ 1330 Nearest Common Ancestors (最近公共祖先)
阿新 • • 發佈:2020-08-09
題目通道: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 }
小結:
沒有小結的小結