UVA - 548 Tree(已知中后序---建树---找路径最小的根节点)

题目链接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;
}

在这里插入图片描述
哈哈

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zaiyang遇见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值