WUSTOJ 1299: 结点选择(Java)
題目鏈接:?1299: 結點選擇
參考:?【Java】 藍橋杯ALGO-4 算法訓練 結點選擇——柳婼 の blog
Description
有一棵n個節點的樹,樹上每個節點都有一個正整數權值。如果一個點被選擇了,那么在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?
Input
多組測試數據
每組第一行包含一個整數n。
接下來的一行包含n個正整數,第i個正整數代表點i的權值。
接下來一共n-1行,每行描述樹上的一條邊。
Output
輸出一個整數,代表選出的點的權值和的最大值。
Simple Input
5 1 2 3 4 5 1 2 1 3 2 4 2 5Sample Output
12Hint
樣例說明
選擇3、4、5號點,權值和為 3+4+5 = 12 。
數據規模與約定
對于20%的數據, n <= 20。
對于50%的數據, n <= 1000。
對于100%的數據, n <= 100000。
權值均為不超過1000的正整數。
分析?
樹的存儲結構原本可以用“孩子表示法”,可是此題的輸入并不是先父結點后子結點,因此,我們不妨用無向圖來看待此樹(樹其實也是圖)。而此題結點數比較大,用“數組表示法”顯然不合適(內存可能不夠),“十字鏈表”和“鄰接多重表”則比較繁瑣,“鄰接表”作為存儲結構最為合適。
采用先序遍歷的算法遍歷整棵樹。
當前子樹的根結點可以選擇,可以不選擇。
如果根結點不選擇,那么它的某個子結點可不選擇,也可選擇。只需選取其中權值較大的那種加到根結點的權值中即可。
如果根結點選擇,那么它的所有子結點都不能選擇。也就是將子結點不選擇的那種的權值加到根結點權值中即可。
不選擇當前子樹的根結點,那么就將它的子結點(子樹)i的權值較大的情況加到根結點中
weight[root][0] += Math.max(weight[i][0], weight[i][1]);
選擇當前子樹的根結點,那么將它的子結點(子樹)i的不選擇的權值加到根結點中
weight[root][1] += weight[i][0];
代碼?
/*** Time 3505ms* @author wowpH* @version 1.1* @date 2019年6月7日上午10:57:35* Environment: Windows 10* IDE Version: Eclipse 2019-3* JDK Version: JDK1.8.0_112*/import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.Scanner;public class Main {private Scanner sc;private static final int MAX_N = 100001;private int n;private int[][] weight;// 權值private List<List<Integer>> adjacencyList;// 鄰接表public Main() {weight = new int[MAX_N][2];// 下標從1開始sc = new Scanner(new InputStreamReader(System.in));while (sc.hasNext()) {adjacencyList = new ArrayList<List<Integer>>();// 頭指針的線性表input();dfs(1, 0);// 1根節點,0無前驅結點System.out.println(Math.max(weight[1][0], weight[1][1]));}sc.close();}private void input() {n = sc.nextInt();// 結點數adjacencyList.add(new ArrayList<Integer>());// 下標從1開始,這個不用for (int i = 1; i <= n; i++) {weight[i][0] = 0; // 初始化為0weight[i][1] = sc.nextInt();// 輸入權值adjacencyList.add(new ArrayList<Integer>());// 創建頭結點}int head, tail;// 弧的頭尾for (int i = 1; i < n; i++) {tail = sc.nextInt();head = sc.nextInt();adjacencyList.get(tail).add(head);// 添加表結點adjacencyList.get(head).add(tail);// 無向圖,添加表結點}}private void dfs(int root, int pre) {// root根,pre前驅結點List<Integer> list = adjacencyList.get(root);// 當前鏈表for (Integer i : list) {if (i != pre) {// 非葉子結點,繼續向下遞歸dfs(i, root);// 不選root點,選root子結點i最大的情況weight[root][0] += Math.max(weight[i][0], weight[i][1]);// 選root點,不選root子結點i的情況weight[root][1] += weight[i][0];}}}public static void main(String[] args) {new Main();} }轉載于:https://www.cnblogs.com/wowpH/p/11060764.html
總結
以上是生活随笔為你收集整理的WUSTOJ 1299: 结点选择(Java)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pip 批量安装包
- 下一篇: 获取Java接口的所有实现类