日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Luogu P1122 最大子树和 树形DP

發布時間:2025/3/15 编程问答 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Luogu P1122 最大子树和 树形DP 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目描述

小明對數學飽有興趣,并且是個勤奮好學的學生,總是在課后留在教室向老師請教一些問題。一天他早晨騎車去上課,路上見到一個老伯正在修剪花花草草,頓時想到了一個有關修剪花卉的問題。于是當日課后,小明就向老師提出了這個問題:

一株奇怪的花卉,上面共連有N 朵花,共有N-1條枝干將花兒連在一起,并且未修剪時每朵花都不是孤立的。每朵花都有一個“美麗指數”,該數越大說明這朵花越漂亮,也有“美麗指數”為負數的,說明這朵花看著都讓人惡心。所謂“修剪”,意為:去掉其中的一條枝條,這樣一株花就成了兩株,扔掉其中一株。經過一系列“修剪“之后,還剩下最后一株花(也可能是一朵)。老師的任務就是:通過一系列“修剪”(也可以什么“修剪”都不進行),使剩下的那株(那朵)花卉上所有花朵的“美麗指數”之和最大。

老師想了一會兒,給出了正解。小明見問題被輕易攻破,相當不爽,于是又拿來問你。

輸入輸出格式

輸入格式:

輸入文件maxsum3.in的第一行一個整數N(1 ≤ N ≤ 16000)。表示原始的那株花卉上共N 朵花。

第二行有N 個整數,第I個整數表示第I朵花的美麗指數。

接下來N-1行每行兩個整數a,b,表示存在一條連接第a 朵花和第b朵花的枝條。

輸出格式:

輸出文件maxsum3.out僅包括一個數,表示一系列“修剪”之后所能得到的“美麗指數”之和的最大值。保證絕對值不超過2147483647。

輸入輸出樣例

輸入樣例#1: 7 -1 -1 -1 1 1 1 0 1 4 2 5 3 6 4 7 5 7 6 7 輸出樣例#1:? 3

說明

【數據規模與約定】

對于60%的數據,有N≤1000;

對于100%的數據,有N≤16000。

?

分析

一道非常基礎的樹形DP啦~

f[i]表示必須包含flower[i]的最大美麗值。然后在樹上深搜亂搞~

首先將當前搜到的點point對應的f[point]初始化為flower[point],因為我們規定了f[i]是必須包含flower[i]的最大美麗值。至于為什么有這樣一個設定是因為我們進行DP是建立在這個花還是完整的基礎上的,也就是說,如果我們還需要flower[point]的某個兒子帶來美麗值,那么flower[i]必須是保留的,不能與根斷開。

然后開始找flower[point]的兒子,這里就有一個問題,為了避免在兩個點之間來回搜索,函數dfs必須有一個參數father代表當前搜到的點的父親。如果在point的兒子里找到的點是father那么直接跳過。類似的方法在之前某到深搜的題里面其實有講過(我記得我有寫博客)。

然后繼續遞歸搜索。

搜完它的下一個兒子以后來看,如果這個兒子帶來的美麗值是正的,那么他對當前節點的美麗值是有貢獻的,把它累加到當前節點的美麗值當中。

多說一句,還是要注意數據范圍(雖然我也不知道為什么我開小了,我明明是按照正確的數據范圍開的),剛才把FRET(Fast Runtime Error Transform)的技能連著升了兩級(╯‵□′)╯︵┻━┻。

程序

1 #include <bits/stdc++.h> 2 using namespace std; 3 const int MAXN = 40000; 4 int n, fw[MAXN], EdgeCount, f[MAXN], Head[MAXN]; 5 struct edge 6 { 7 int Next, Aim; 8 }Edge[MAXN]; 9 void insert(int u, int v) 10 { 11 Edge[++EdgeCount] = (edge){Head[u], v}; 12 Head[u] = EdgeCount; 13 } 14 void dfs(int point, int father = 0) 15 { 16 f[point] = fw[point]; 17 // flower point must be in f[point] 18 for (int i = Head[point]; i; i = Edge[i].Next) 19 { 20 int u = Edge[i].Aim; 21 if (u == father) 22 continue; 23 dfs(u,point); 24 if (f[u] > 0) 25 f[point] += f[u]; 26 // if f[u]>0 then it can contribute to f[point] 27 } 28 } 29 int main() 30 { 31 cin >> n; 32 for (int i = 1; i <= n; i++) 33 cin >> fw[i]; 34 for (int i = 1; i < n; i++) 35 { 36 int u, v; 37 cin >> u >> v; 38 insert(u,v); 39 insert(v,u); 40 } 41 dfs(1); 42 int ans = fw[1]; 43 for (int i = 1; i <= n; i++) 44 ans = max(ans, f[i]); 45 cout << ans << endl; 46 getchar(); 47 getchar(); 48 return 0; 49 }

?

轉載于:https://www.cnblogs.com/OIerPrime/p/8439389.html

總結

以上是生活随笔為你收集整理的Luogu P1122 最大子树和 树形DP的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。