Uva - 548 - Tree


这道题目的输入需要注意,一般的都是先说测试数据包含多少个数据,比如中序遍历有多少个结点,再输入,而这里直接输入,回车判断是否结束,所以输入的时候可以先读一行,再用流存入数组。题目说了结点的权值各不相同而且都是正整数,所以直接用权值作为编号。递归的生成二叉树,不过这里可以不用结构体存放,用两个数组存放每个位置左右结点位置。最后用dfs深度优先遍历递归的计算最优解。

最后吐槽一下今天Uva真是跪了好几次,这么古老的网站,网站稳定性也有点古老了。。。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <stack>
#include <queue>
#include <bitset> 
#include <cassert> 

using namespace std;

const int maxv = 10005;
// 各个结点的权值各不相同且都是正整数,可以直接用权值作为结点编号
int inOrder[maxv], postOrder[maxv], lch[maxv], rch[maxv];
int n;

// 因为不知道每次测试数据的输入量,所以读取一行,然后再填入数组中
bool readList(int* a)
{
	string line;
	if (!getline(cin, line)) { // 非法输入,结束
		return false;
	}
	n = 0;
	int x;
	stringstream ss(line);
	while (ss >> x) { // 将数字取出存入数组
		a[n++] = x;
	}
	return n > 0;
}

// 递归构造二叉树,返回树根
int build(int L1, int R1, int L2, int R2)
{
	if (L1 > R1) {
		return 0; // 空树
	}
	int root = postOrder[R2]; // 后序遍历的最后一个结点是根节点
	int p = L1;
	while (inOrder[p] != root) { // 在中序遍历中找到根节点
		p++;
	}
	int cnt = p - L1; // 找到后计算出左结点的个数
	lch[root] = build(L1, p - 1, L2, L2 + cnt - 1); // 递归左子树构造二叉树
	rch[root] = build(p + 1, R1, L2 + cnt, R2 - 1); // 递归右子树构造二叉树
	return root;
}

int best, bestSum;

// DFS深度优先遍历
void dfs(int u, int sum) {
	sum += u;
	if (!lch[u] && !rch[u]) {
		if (sum < bestSum || (sum == bestSum && u < best)) {
			best = u;
			bestSum = sum;
		}
	}
	if (lch[u]) {
		dfs(lch[u], sum);
	}
	if (rch[u]) {
		dfs(rch[u], sum);
	}
}

int main()
{
	while (readList(inOrder)) { // EOF停止
		readList(postOrder);
		build(0, n - 1, 0, n - 1);
		bestSum = 1000000000;
		dfs(postOrder[n - 1], 0);
		cout << best << endl;
	}

	return 0;
}




posted @ 2015-06-15 23:05  Say舞步  阅读(159)  评论(0编辑  收藏  举报