题目链接:https://cn.vjudge.net/contest/317394#problem/I
Sample Input
3 2 1 4 5 7 6
3 1 2 5 6 7 4
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
255
255
Sample Output
1
3
255
翻译:给出的是中序遍历和后序遍历,求从根节点到叶节点的最短路径所对应的叶节点的值
分析:
建树是第一步,建好后从根节点出发,先左后右,找路径最小的根节点,路径相同时,输出根节点最小的。
建树的注意:给出的是后序,所以先建右子树,右子树建完以后,在进行左子树的构建。返回父亲节点的条件是,所对应的区间小于或等于0。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100005
#define INF 0x3f3f3f3f
int mid[N],behid[N];
int mi,ans;
struct node {
int val;
node *l,*r;
};
node *build(int x,int y,int z) {
if(z<=0)
return NULL;
node *root=new node;
root->val=behid[y];/*y为后序中的第y个位置上的值*/
int u,d;
for(int i=x; i>=0; i--) { /*x为中序所剩的范围*/
if(mid[i]==behid[y]) {
u=i;
break;
}
}
d=x-u;/*子树的范围*/
root->r=build(x,y-1,d);/*遍历右子树,对应的中序中的范围最右边的范围不变*/
root->l=build(u-1,y-1-d,z-1-d);/*遍历左子树,最右边的范围变成u-1,左子树的范围等于总范围减去右子树的范围再减去根节点本身*/
return root;
}
void solve(node *root,int sum) {
if(root==NULL)
return;
if(root->l==root->r&&root->l==NULL) {
if(sum+root->val<mi) {
mi=sum+root->val;
ans=root->val;
} else if(sum+root->val==mi) {
if(ans>root->val)
ans=root->val;
}
}
solve(root->l,sum+root->val);
solve(root->r,sum+root->val);
}
int main() {
char a[N];
while(gets(a)) {
int x=0,k=0;
for(int i=0; i<strlen(a); i++) {
if(a[i]==' ') {
mid[k++]=x;
x=0;
} else
x=x*10+a[i]-'0';
}
mid[k++]=x;/*中序遍历*/
for(int i=0; i<k; i++)
scanf("%d",&behid[i]);/*后序遍历*/
getchar();
node *root;
root=build(k-1,k-1,k);/*建树*/
mi=INF;
solve(root,0);
printf("%d\n",ans);
}
return 0;
}
哈哈