1. 程式人生 > 其它 >洛谷P1122—最大子樹和(樹形DP)

洛谷P1122—最大子樹和(樹形DP)

做了好幾個樹形DP的題,這道題就簡單多了

題意

有N多花,有N-1條邊,每朵花有美麗指數(可能為負),可以通過修剪,使剩下的一株美麗指數和最大,求最大的美麗指數之和

輸入輸出

第一行N
第二行N個美麗指數
接下啦N-1行,花與花之間的邊

思路

這道題需要建雙向邊,關係不明確。是自底向上的樹形DP
狀態轉移陣列 dp[i]為以i為根節點的子樹的美麗指數之和
狀態轉移關係dp[u] = max(dp[u],dp[u] + dp[v])
如果子結點的美麗指數為負數,就不加上它的美麗指數

#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;
}

作者:inss!w! 出處:https://www.cnblogs.com/Hfolsvh/ 版權宣告:本部落格所有文章除特別宣告外,均採用 BY-NC-SA 許可協議。轉載請註明出處!