https://vjudge.net/problem/UVA-548
题意:给一棵树的中序和后序遍历 找一个叶子使它到根路径上的权合最小
呜呜呜。。。终于要面对一直学不会的东西了
思路:递归思想 后序遍历最后遍历的一定是根结点 因此可以在中序遍历中找到左右子树 之后我们可以从左子树的部分那些节点中 从后序遍历中找他们的根节点 之后不断地便利下去 找权合最小的 再遍历一边 这个不是重点 我们拿样例来摸你一下这个神奇的过程




#include<algorithm>
#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<ctime>
#include<map>
#include<stack>
#include<set>
#include<cstring>
#include<sstream>
#include<queue>
using namespace std;
const int maxn = 10005;
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(line);
n = 0;
int x;
while (ss >> x) {
a[n++] = x;
}
return n > 0;
}
int build(int L1, int R1, int L2, int R2) {//L1 R1对应中序序列 L2 R2对应后序序列
//cout << L1 << ' ' << R1 << ' ' << L2 << ' ' << R2 << endl;
if (L1 > R1) return 0;
int root = post_order[R2];//后序遍历的最后一个节点
int p = L1;//从中序的第一个节点开始找
while (in_order[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, best_num;
void dfs(int u, int sum) {
sum += u;
if (!lch[u] && !rch[u]) {
if (sum < best_num || (sum == best_num && u < best)) {
best = u;
best_num = sum;
}
}
if (lch[u]) dfs(lch[u], sum);
if (rch[u]) dfs(rch[u], sum);
}
int main() {
while (read_list(in_order)) {
read_list(post_order);
build(0, n - 1, 0, n - 1);
best_num = 0x3f3f3f3f;
dfs(post_order[n - 1], 0);//根节点
cout << best << endl;
}
return 0;
}







Comments | NOTHING