UVA-548
题意:给出中序和后序,求路根到叶子节点径和最小的那个叶子节点。
解题思路:从后序中找到根节点,中序中根节点左边的是它的左子树,根节点右边的是它的右子树。然后不断处理,直到叶子节点两边无法再分,取最小的那个。
首先我们定义一个函数dfs(int now, int l, int r, int sum)。l,r是当前处理的范围是中序中的 l 到 r 这段树。now是当前是以后序中的第n个作为根节点。sum是到当前节点之前的路径和。
//map[i]表示后序中第i个的值,w[x]表示数字x在中序中的位置。
判断叶子节点:当l == r代表当前处理范围只有一个数,则就是叶子节点了。
左子树和右子树的now ,l , r 是多少?
首先对于右子树,它的now是now-1(后序遍历,如果存在右子树,右子树的根就是在它的前一个)。我们知道w[map[now]]的值,那么中序中 w[map[now]]+1 到 r 就是它的处理范围。
对于左子树,它的now应该是now扣除掉右子树中节点的个数,又知道右子树的范围,减一下就有来。左子树的处理范围 为l 到 w[map[now]]-1。
/*************************************************************************
> File Name: UVA-548.cpp
> Author: Narsh
>
> Created Time: 2016年07月18日 星期一 15时30分43秒
************************************************************************/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int map[110000],n,m,t,w[110000];
char c;
int ansum,ans;
void dfs(int now, int l, int r, int sum) {
sum+=map[now];
// if (map[now] == 0) return ;
if (l > r) return ;
if (l == r) {
if (sum < ansum) {
ansum=sum;
ans=map[now];
}
return ;
}
dfs(now-1,w[map[now]]+1,r,sum);
dfs(now-1-r+w[map[now]],l,w[map[now]]-1,sum);
}
int main() {
while (scanf("%d%c",&t,&c) != EOF){
n=1;w[t]=n;
while (c !='\n') {
scanf("%d%c",&t,&c);
n++;
w[t]=n;
}
for (int i = 1; i <= n; i++) {
scanf("%d%c",&t,&c);
map[i]=t;
}
int sum,r;
ansum=999999999;
dfs(n,1,n,sum);
printf("%d\n",ans);
}
}