动态规划 树形DP (最大连续子序列和 与 树上DP) 洛谷P1122

 动态规划 树形DP (最大连续子序列和 与 树上DP) 洛谷P1122

题目描述
小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题。一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题。于是当日课后,小明就向老师提出了这个问题:

一株奇怪的花卉,上面共连有N N朵花,共有N-1N−1条枝干将花儿连在一起,并且未修剪时每朵花都不是孤立的。每朵花都有一个“美丽指数”,该数越大说明这朵花越漂亮,也有“美丽指数”为负数的,说明这朵花看着都让人恶心。所谓“修剪”,意为:去掉其中的一条枝条,这样一株花就成了两株,扔掉其中一株。经过一系列“修剪“之后,还剩下最后一株花(也可能是一朵)。老师的任务就是:通过一系列“修剪”(也可以什么“修剪”都不进行),使剩下的那株(那朵)花卉上所有花朵的“美丽指数”之和最大。

老师想了一会儿,给出了正解。小明见问题被轻易攻破,相当不爽,于是又拿来问你。

输入输出格式
输入格式:
第一行一个整数N(1 ≤ N ≤ 16000)N(1≤N≤16000)。表示原始的那株花卉上共N N朵花。

第二行有N N个整数,第II个整数表示第II朵花的美丽指数。

接下来N-1N−1行每行两个整数a,ba,b,表示存在一条连接第aa 朵花和第bb朵花的枝条。

输出格式:
一个数,表示一系列“修剪”之后所能得到的“美丽指数”之和的最大值。保证绝对值不超过21474836472147483647。

输入输出样例
输入样例#17
-1 -1 -1 1 1 1 0
1 4
2 5
3 6
4 7
5 7
6 7
输出样例#13
说明
【数据规模与约定】

对于60%60%的数据,有N≤1000N≤1000;

对于100%100%的数据,有N≤16000N≤16000

用了 树上DP + 最大连续子序列和题目

假设我们从 -2 结点 开始搜索,为了方便表示,用结点值代表结点编号

用DP{i} 记录取以i为根的子树最大的收益是多少的最大值。

以 -2结点 作为子树序列的尾(根),叶结点 3,-10,8 作为子树序列的头部 (叶)

那么就有 3个 以-2结尾的子树序列 {-2,-10,8} {-2,3} {-2,6},这三个子树序列共同构成了以 - 2 为根的子树

以序列① {8,10,-2}  开始,

dp{8}  = 8, ( 8作为结尾)

dp[-10} = 8 + (-10) = -2

dp{-2} = -2 (因为 dp{-10} < 0 )

以序列② {3,-2}  开始,

dp{3} = 3,

dp{-2} = 3 + dp{-2} = 1

以序列② {3,-2}  开始,

dp{6} = 6

dp{-2} = 6 + dp {-2} =  6 + 1 = 7

求出 每个结点dp值 的最大值就是答案了。

DP思想:

  用DP{i} 记录取以i为根的子树最大的收益是多少的最大值。

#include <iostream>
#include <algorithm>
#include <vector> 
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 1;
vector<vector<int> > node(N,vector<int>());
int v[N],vis[N];
int dp[N];
int n;
int ans;

void dfs(int u,int fa){//u表示当前结点,fa表示父结点 
    dp[u] = v[u];
    for(int i=0;i<node[u].size();++i){
        int v = node[u][i];
        if(v != fa){//避免回到父结点 
            dfs(v,u);
            if(dp[v] > 0){
                dp[u] += dp[v];
            }
        }
    }
}

int main(){
    ios::sync_with_stdio(false);
     
    cin >> n;
    int a,b;
    for(int i=1;i<=n;++i){
        cin >> v[i];
    }
    for(int i=1;i<=n-1;++i){
        cin >> a >> b;
        node[a].push_back(b);
        node[b].push_back(a);
    }
    
    dfs(1,0);
    ans = -INF;
    for(int i=1;i<=n;++i){
        ans = max(ans,dp[i]);
    }
    cout << ans << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/--zz/p/10585109.html