A

来源:互联网 发布:网络的好处 英语作文 编辑:程序博客网 时间:2024/05/29 12:49
            A - Nearest Common Ancestors

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

题目的大意在这里就不说啦,大家自己翻译一下 锻炼一下英语 ,或者 有道翻译都行,写这个题的时候 刚学啦RMQ 和 LCE 求解 共同祖先的问题,其实 思路是很简单的,但是 构建树的时候需要用到邻接表 来存储数据。简单说一下 解题的思路把,就是 当你将树构建好,而且用一个数组F【N】来存储 每一个 节点的父节点,然而应为 dfs 的时候要从根节点开始, 这里还要求一下 根节点,大家想一下 是不是除了根节点以外的节点 是不是都有 它的 父节点,这里 利用F[N] 循环一下就可以求出 根节点啦, 然后在 dfs 的时候 用一个数组depth[N] 存储 每一个节点的 深度 (根节点的深度为0), 好啦 所有的准备工作已经做好啦,接下来该 求解 公共祖先啦,下面的 程序就简单啦 ,大家 看看下面的代码就OK 啦。另外 提醒一下,vector arr[N] 中 这个数组的 下标 是从 0 开始的 ,如果 你的数据不是从零开始的 那么 在 dfs 中 要 i = 0 的情况 用 continue 跳过 就行啦;

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;int f[10010];// 存储父节点int d[10010];// 存储每一个节点的深度vector<int> arr[10010];// 用邻接表 构建 树void dfs(int u, int dep){    d[u] = dep;    for(vector<int>::iterator it = arr[u].begin(); it != arr[u].end(); it++)        if(*it == 0) continue;// 跳过  it = 0 的时候 跳过        else dfs(*it, dep+1);}int main(){    int t; cin>>t;    while(t--)    {        int x, y, n;        scanf("%d", &n);        for(int i = 1; i <= n; i++)        {            arr[i].clear();            f[i] = -1;        }        for(int i = 1; i < n; i++)        {            scanf("%d%d", &x, &y);            arr[x].push_back(y);            f[y] = x;        }        int k;        for(k = 1; f[k] >= 0; k++);// 找出 根节点        dfs(k, 0);        scanf("%d%d", &x, &y);        while(x != y)        {            if(d[x] > d[y])                x = f[x];            else                y = f[y];        }        printf("%d\n", x);    }    return 0;}

下面 是我新学的 一个方法 , 是根据 一直 回溯 祖先值, 并 把 回溯过程中的祖先值 都标记一下, 然后在回溯 另一个 节点的 祖先值 ,在回溯的过程中 如果 遇到一个 祖先值 已经被标记啦, 就将这个 祖先值 输出 ,这个就是所求解的 共同的祖先;

下面请看代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;struct TreeNode{    int father;    int mark;}tree[10005];void LCA(int x, int y){    tree[x].mark = true;    x = tree[x].father;    while(x != tree[x].father)    {        tree[x].mark = true;        x = tree[x].father;    }    while(y != tree[y].father)    {        if(tree[y].mark == true)            break;        y = tree[y].father;    }    printf("%d\n", y);// 这个如果放在里面的话 会WA 应为 while  循环有时候 进不去的  那么就会出现没有输出的的情况}int main(){    int t; cin>>t;    while(t--)    {        int n, x, y;        scanf("%d", &n);        for(int i = 0; i <= n; i++)// 先进性初始化        {            tree[i].father = i;            tree[i].mark = false;        }        for(int i = 1; i < n; i++)        {            scanf("%d%d", &x, &y);            tree[y].father = x;        }        scanf("%d%d", &x, &y);        LCA(x, y);    }    return 0;}
原创粉丝点击