UVA 548 Tree

树,存个代码慢慢想

 1 // UVa548 Tree
 2 // Rujia Liu
 3 // 题意:给一棵点带权(权各不相同,都是正整数)二叉树的中序和后序遍历,找一个叶子使得它到根的路径上的权和最小。如果有多解,该叶子本身的权应尽量小
 4 // 算法:递归建树,然后DFS。注意,直接递归求结果也可以,但是先建树的方法不仅直观,而且更好调试
 5 #include<iostream>
 6 #include<string>
 7 #include<sstream>
 8 #include<algorithm>
 9 using namespace std;
10 
11 // 因为各个结点的权值各不相同且都是正整数,直接用权值作为结点编号
12 const int maxv = 10000 + 10;
13 int in_order[maxv], post_order[maxv], lch[maxv], rch[maxv];
14 int n;
15 //lch,rch 的下标index对应的位置就是某个值为inndex的左右子树
16 //比如lch[6]就是权值为6的节点的左子树,为0则说明没有左子树
17 bool read_list(int* a) {
18     string line;
19     if (!getline(cin, line)) return false;
20     stringstream ss(line);
21     n = 0;
22     int x;
23     while (ss >> x) a[n++] = x;
24     return n > 0;
25 }
26 
27 // 把in_order[L1..R1]和post_order[L2..R2]建成一棵二叉树,返回树根
28 int build(int L1, int R1, int L2, int R2) {
29     if (L1 > R1) return 0; // 空树
30     int root = post_order[R2];
31     int p = L1;
32     while (in_order[p] != root) p++;
33     int cnt = p - L1; // 左子树的结点个数
34     lch[root] = build(L1, p - 1, L2, L2 + cnt - 1);
35     rch[root] = build(p + 1, R1, L2 + cnt, R2 - 1);
36     return root;
37 }
38 
39 int best, best_sum; // 目前为止的最优解和对应的权和
40 
41 void dfs(int u, int sum) {
42     sum += u;
43     if (!lch[u] && !rch[u]) { // 叶子
44         if (sum < best_sum || (sum == best_sum && u < best)) { best = u; best_sum = sum; }
45     }
46     if (lch[u]) dfs(lch[u], sum);
47     if (rch[u]) dfs(rch[u], sum);
48 }
49 
50 int main() {
51     while (read_list(in_order)) {//
52         read_list(post_order);//后序                                  
53         build(0, n - 1, 0, n - 1);
54         best_sum = 1000000000;
55         dfs(post_order[n - 1], 0);
56         cout << best << "\n";
57     }
58     return 0;
59 }

 

posted @ 2019-03-14 21:02  付玬熙  阅读(134)  评论(0编辑  收藏  举报