关闭

UVA 548 Tree

69人阅读 评论(0) 收藏 举报
分类:

题目链接 http://acm.hust.edu.cn/vjudge/problem/19105


题意:给定前序和后序遍历,找出从根到叶sum最小的路径,然后输出叶子上的值,如果有多条路径满足,输出叶子权值最小的。
分析:后序遍历的最后一个数就是根的值,因此只需在中序遍历中找到它,就知道左右子树的中序和后序遍历了。然后在不断递归,构造二叉树。 最后dfs找路径权值和最小的 


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <stack>
#include <string>
#include <sstream>
#include <map>
#include <set>
#define pi acos(-1.0)
#define LL long long
#define ULL unsigned long long
#define inf 0x3f3f3f3f
#define INF 1e18
//#define lson l,mid,rt<<1
//#define rson mid+1,r,rt<<1|1
#define Deb(a) printf("---%d---\n", a);
#define mem0(a) memset(a, 0, sizeof(a))
#define memi(a) memset(a, inf, sizeof(a))
#define mem1(a) memset(a, -1, sizeof(a))
using namespace std;
typedef pair<int, int> P;
const double eps = 1e-10;
const int maxn = 1e6 + 5;
const int mod = 1e8;

int in_order[maxn], post_order[maxn];
int ans, mni, node, n;
struct Node{
	int lson, rson, val;
}tree[maxn];

bool read_list(int* a)
{
	string line;
	getline(cin, line);
	stringstream ss;
	ss << line;
	int x;
	n = 0;
	while (ss >> x) a[++n] = x;
	return n > 0;
}
int NewNode(int v){
	tree[++node].val = v;
	return node;
}
// 把in_oreder[L1..R1] 和 post_order[L2..R2]建成一棵二叉树,返回树根 
int MakeTree(int L1, int R1, int L2, int R2)
{
	if (L1 > R1) return 0; // 空树 
	int root = NewNode(post_order[R2]);
	int p = L1, cnt = 0;
	while (in_order[p] != post_order[R2]) 
		p++, cnt++;			// cnt为左子树的结点个数 
	int rootl = MakeTree(L1, L1+cnt-1, L2, L2+cnt-1);
	int rootr = MakeTree(p+1, R1, L2+cnt, R2-1);
	tree[root].lson = rootl;
	tree[root].rson = rootr;
	return root;
}
void dfs(int root, int sum)
{
	sum += tree[root].val;
	if (!tree[root].lson && !tree[root].rson){	// 叶子结点 
		if (mni > sum || (mni == sum && ans > tree[root].val))
			mni = sum, ans = tree[root].val;
		return;
	}
	if (tree[root].lson)
		dfs(tree[root].lson, sum);
	if (tree[root].rson)
		dfs(tree[root].rson, sum);
}
int main(void)
{
//	freopen("C:\\Users\\wave\\Desktop\\NULL.exe\\NULL\\in.txt","r", stdin);
	while (read_list(in_order)){
		read_list(post_order);
		node = 0; 
		int root = MakeTree(1, n, 1, n);
		mni = ans = inf;
		dfs(root, 0);
		printf("%d\n", ans);
	}

	return 0;
}


还有一种简单一点的做法,因为题目说各个点的权值不相同,所以可以直接把权值当做结点编号

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <stack>
#include <string>
#include <map>
#include <set>
#include <sstream>
#define pi acos(-1.0)
#define LL long long
#define ULL unsigned long long
#define inf 0x3f3f3f3f
#define INF 1e18
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define debug(a) printf("---%d---\n", a)
#define mem0(a) memset(a, 0, sizeof(a))
#define memi(a) memset(a, inf, sizeof(a))
#define mem1(a) memset(a, -1, sizeof(a))
using namespace std;
typedef pair<int, int> P;
const double eps = 1e-10;
const int maxn = 1e6 + 5;
const int mod = 1e8;

// 因为各个结点的权值各不相同且都是正整数, 直接用权值作为结点编号 
int in_order[maxn], post_order[maxn], lch[maxn], rch[maxn];
int n;

bool read_list(int* a){
	string line;
	if (!getline(cin, line)) return false;
	stringstream ss;
	ss << line; 
	n = 0;
	int x;
	while (ss >> x) a[n++] = x;
	return n > 0;
} 
// 把in_oreder[L1..R1] 和 post_order[L2..R2]建成一棵二叉树,返回树根 
int build(int L1, int R1, int L2, int R2){
	if (L1 > R1) return 0; // 空树 
	int root = post_order[R2];
	int p = L1, cnt = 0;
	while (in_order[p] != root) p++, cnt++; // cnt为左子树的结点个数 
	lch[root] = build(L1, L1+cnt-1, L2, L2+cnt-1);
	rch[root] = build(p+1, R1, L2+cnt, R2-1);
	return root;
}
int best, best_sum; 
void dfs(int u, int sum){
	sum += u;
	if (!lch[u] && !rch[u]){ // 叶子结点 
		if (sum < best_sum || (sum == best_sum && u < best)){
			best = u;
			best_sum = sum;
		}
	}
	if (lch[u]) dfs(lch[u], sum);
	if (rch[u]) dfs(rch[u], sum);
}

int main(void)
{
//	freopen("C:\\Users\\wave\\Desktop\\NULL.exe\\NULL\\in.txt","r", stdin);
	while (read_list(in_order)){
		read_list(post_order);
		int root = build(0, n-1, 0, n-1);
		best_sum = inf;
		dfs(root, 0);
		cout << best << endl;
	}

	return 0;
}



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:8279次
    • 积分:1151
    • 等级:
    • 排名:千里之外
    • 原创:112篇
    • 转载:0篇
    • 译文:0篇
    • 评论:8条