Tree UVA - 548

29 篇文章 0 订阅
6 篇文章 0 订阅

UVA-548

题目:给一棵点带权(权值各不相同,都是小于10000的正整数)的二叉树的中序和后序遍历,找一个叶子使得它到根的路径上的权和最小。如果有多解,该叶子本身的权应尽量小。输入中每两行表示一棵树,其中第一行为中序遍历,第二行为后序遍历。(题目翻译取自刘汝佳《算法竞赛入门经典》P155)。

#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<sstream>
using namespace std;
const int MAXN = 20000;
int inOrder[MAXN],postOrder[MAXN],l_tree[MAXN],r_tree[MAXN];
int best,best_leave,n;
bool input(int *a){
    string s;
    while(!getline(cin,s)) return false;
    stringstream ss(s);
    int x;
    n = 0;
    while(ss>>x) a[n++] = x;
    return n>0;
}
int build(int L1,int R1,int L2,int R2){
    if(L1>R1) return 0; //为空树
    int root = postOrder[R2]; 
    int p = L1;
    while(inOrder[p]!=root) p++;
    int count = p - L1; //根坐标为root的左子树的节点个数
    l_tree[root] = build(L1, p-1, L2, L2+count-1); //l_tree[root]指 根坐标为root的左子树的根坐标的值
    r_tree[root] = build(p+1, R1, L2+count, R2-1); //r_tree[root]指 根坐标为root的右子树的根坐标的值
    return root;
}
void dfs(int u,int sum){
    sum += u;
    if(!l_tree[u]&&!r_tree[u]){ //根坐标为u的节点没有左子树也没有右子树,则u是一片叶子
        if(sum<best||(sum==best&&u<best_leave)){
            best = sum; //到目前为止的最优解的对应权值和
            best_leave = u;
        }
    }
    if(l_tree[u]) dfs(l_tree[u],sum); 
    if(r_tree[u]) dfs(r_tree[u],sum);
}
int main()
{
    while(input(inOrder)){
        input(postOrder);
        build(0,n-1,0,n-1);
        best = 1<<30; //best取很大数
        dfs(postOrder[n-1],0);
        cout<<best_leave<<endl;
    }
    return 0;
}


思路:后序遍历的最后一个字符是根,因此只需在中序遍历中找到它,就知道左右子树的中序和后序遍历了。从而可以据此构造二叉树。最后递归遍历,求出最优解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值