1. 程式人生 > >UVA 548 Tree

UVA 548 Tree

樹根 best 最優解 題意 algorithm include 個數 二叉樹 als

樹,存個代碼慢慢想

 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 }

UVA 548 Tree