洛谷P1122—最大子樹和(樹形DP)
阿新 • • 發佈:2021-07-17
做了好幾個樹形DP的題,這道題就簡單多了
題意
有N多花,有N-1條邊,每朵花有美麗指數(可能為負),可以通過修剪,使剩下的一株美麗指數和最大,求最大的美麗指數之和
輸入輸出
第一行N
第二行N個美麗指數
接下啦N-1行,花與花之間的邊
思路
這道題需要建雙向邊,關係不明確。是自底向上的樹形DP
狀態轉移陣列 dp[i]為以i為根節點的子樹的美麗指數之和
狀態轉移關係dp[u] = max(dp[u],dp[u] + dp[v])
如果子結點的美麗指數為負數,就不加上它的美麗指數
作者:inss!w! 出處:https://www.cnblogs.com/Hfolsvh/ 版權宣告:本部落格所有文章除特別宣告外,均採用 BY-NC-SA 許可協議。轉載請註明出處!#include <iostream> #include<algorithm> #include<cmath> using namespace std; const int MAX_N = 20000; //最多結點數 int tot; //標記邊的序號 int head[MAX_N << 1],nxt[MAX_N << 1],ver[MAX_N << 1],edge[MAX_N << 1]; //建樹要用到的陣列 int dp[MAX_N]; int r[MAX_N]; void addedge(int u,int v){ //根據鄰接表建樹的過程 ver[++tot] = v; //tot條邊指向的點為v nxt[tot] = head[u]; //nxt儲存以u為始點的下一條邊的序號 head[u] = tot; //head[u]儲存以u為始點的邊的序號 } void dfs(int u,int fa){ dp[u] = r[u]; for(int i = head[u];i;i = nxt[i]){ int v = ver[i]; if(v == fa) continue; dfs(v,u); dp[u] = max(dp[u],dp[u] + dp[v]); } } int main(){ int n; cin >> n; for(int i = 1;i <= n;i++) cin >> r[i]; int u,v; for(int i = 0;i < n - 1;i++){ cin >> u >> v; addedge(u,v); addedge(v,u); } dfs(1,0); int ans = -1e8; //初始值要是一個很小的數 for(int i = 1;i <= n;i++){ ans = max(ans,dp[i]); } cout << ans; return 0; }