zoukankan      html  css  js  c++  java
  • 洛谷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!
    版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 相关阅读:
    0714买卖股票的最佳时机含手续费 Marathon
    0070爬楼梯 Marathon
    0045跳跃游戏II Marathon
    0343整数拆分 Marathon
    0406根据身高重建队列 Marathon
    0096不同的二叉搜索树 Marathon
    0763划分子母区间 Marathon
    0435无重叠区间 Marathon
    0452用最少数量的箭引爆气球 Marathon
    0509斐波那契数 Marathon
  • 原文地址:https://www.cnblogs.com/Hfolsvh/p/15021998.html
Copyright © 2011-2022 走看看