UVa 548

题意

给出一棵带权二叉树的中序和后序遍历
找一个叶子使得它到根的路径上的权和最小。
如果有多解,该叶子本身的权应尽量小

思路

学习了一下紫书给的思路和代码

先根据中序和后序遍历构造二叉树
根据后序遍历找到树根,然后在中序遍历中找到树根,从而找出左右子树的结点列表,然后递归构造左右子树。
最后用DFS求最小权和

AC代码

#include <iostream>
#include <string>
#include <sstream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 10000 + 10;
int mid[maxn], after[maxn], l[maxn], r[maxn];
int best, sum, n;

bool read_getline( int *s ){
    string line;
    if( !getline(cin,line) )    return false;
    stringstream ss(line);
    n = 0;
    int x;
    while( ss >> x )    s[n++] = x;
    if(n > 0)  return true;
    return false;
}

int build( int l1, int r1, int l2, int r2 ){

    if( l1 > r1 )   return 0;
    int root = after[r2];
    int p = l1;
    while( mid[p] != root )     p++;
    int tmp = p - l1;
    l[root] = build(l1, p-1, l2, l2+tmp-1);
    r[root] = build(p+1, r1, l2+tmp, r2-1);
    return root;
}

void DFS( int t, int all )
{
    all += t;
    if( !l[t] && !r[t] )
        if( all < sum || (all == sum && t < best) ){
            best = t;
            sum = all;
        }
    if(l[t]) DFS(l[t], all);
    if(r[t]) DFS(r[t], all);
}

int main()
{
    while( read_getline(mid) )
    {
        read_getline(after);
        build(0, n-1, 0, n-1);
        sum = 1000000000;
        DFS(after[n-1], 0);
        cout << best << endl;
        memset(mid,0,sizeof(mid));
        memset(after,0,sizeof(after));
        memset(l,0,sizeof(l));
        memset(r,0,sizeof(r));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/JinxiSui/p/9740609.html