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