PAT甲级1151 LCA in a Binary Tree (30point(s))

 求 LCA,当然,不用真写个 LCA 算法出来(tarjan 什么的)。题目给了树的中序遍历和先序遍历,我们不需要先把树建起来,而是可以在建树的过程中,找出两个结点的 LCA。

具体的想法是,当两个结点不同时,它们必分布在它们的 LCA 的两侧,结合给出的中序遍历,分布在两侧的结点在中序遍历中相对根结点的位置也正好是一前一后。根据这个性质,我们就可以按照建树的方法,先在前序遍历中找根,然后在中序遍历中把两棵子树找出来,看看两个结点是否分布在两棵不同的子树上。反复查找直到找到满足的情况,第一次令两个结点分布在两棵不同子树上的根结点,就是要找的 LCA。

而判断是否在两棵不同的子树上的方法,就是分别计算它们的下标与当前根结点的下标的差值。前面说到,当找到 LCA 时,两个结点在中序遍历的位置必定在根结点的一前一后。这时,分别用根结点的下标减去两个结点的下标,得到两个差的乘积必定是负数。若乘积为 0,则说明其中一个结点的下标与根结点相同,说明它们是同一个结点,那么它们的 LCA 就是这个结点。若乘积为正数,说明它们在同一侧,还需要继续。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e4+4;
int m, n;
int pre[maxn], in[maxn];
map<int, int> inid;

void read() {
    scanf("%d%d", &m, &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &in[i]);
        inid[in[i]] = i; //先保存各个结点在inorder下的下标,加速
    }
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &pre[i]);
    }
}

void find(int u, int v, int rid) {
    if (rid > n) return; //边界处理

    int rt = pre[rid]; //当前检查的根
    int rpos = inid[rt]; //根在inorder下的下标
    int udif = INF, vdif = INF; //udif、vdif分别为u、v与根的下标的差值
    if (inid.count(u)) udif = rpos - inid[u]; //如果存在,计算差值
    if (inid.count(v)) vdif = rpos - inid[v]; //如果不存在,值为默认的INF

    if (udif == INF && vdif != INF) { //先检查u、v是否存在
        printf("ERROR: %d is not found.\n", u);
    } else if (udif != INF && vdif == INF) {
        printf("ERROR: %d is not found.\n", v);
    } else if (udif == INF && vdif == INF) {
        printf("ERROR: %d and %d are not found.\n", u, v);
    } else if (udif*vdif < 0) { //如果都存在,且差值的乘积为负数,说明在根的两侧
        printf("LCA of %d and %d is %d.\n", u, v, rt);
    } else if (udif*vdif == 0) { //如果为0,说明其中一个与根相等
        printf("%d is an ancestor of %d.\n", rt, u == rt ? v : u);
    } else if (udif*vdif > 0) { //如果为正数,说明在根的同一侧,继续分析
        find(u, v, rid+1); //写了个尾递归。。可以改成循环
    }
}

void solve() {
    while (m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        find(u, v, 1);
    }
}

int main() {
    read();
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/HNUCSEE_LJK/article/details/108218965