题意
给出一棵带权二叉树的中序和后序遍历
找一个叶子使得它到根的路径上的权和最小。
如果有多解,该叶子本身的权应尽量小
思路
学习了一下紫书给的思路和代码
先根据中序和后序遍历构造二叉树
根据后序遍历找到树根,然后在中序遍历中找到树根,从而找出左右子树的结点列表,然后递归构造左右子树。
最后用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;
}