洛谷 P1122 最大子树和

本文讨论了一道关于树形结构的问题,利用动态规划方法解决,涉及如何在不确定父节点的情况下枚举并计算每个节点的最大价值。通过深度优先搜索处理节点间的父子关系,最后给出了C++代码实现。
摘要由CSDN通过智能技术生成

思路:树形DP

这道题来说,看到了N个结点,但是N-1个枝头,我们就该想到了什么?肯定是树啊,这个肯定就是树的结构嘛,因为树的结点个数=树的边数+1.

好了,既然知道是树的数据结构了,他让我们求最大的价值,不出意外,就是个DP,或者贪心。后来我们发现,这里的结点也是有联系的,但是不知道谁是父节点谁是子节点,所以这个时候就需要我们枚举每一个结点作为父节点进行讨论了。到了这一步应该很清楚了,是DP才对,因为这里涉及到递推的过程。

入门的哪个宴会,其实是明确的指出了谁是父节点谁是子节点的关系,我们这个既然不确定了肯定是把所有可能性都列举一遍呗,所以dfs中的第二个变量存储的就是fa父节点,一方面是为了递推下去,一方面是为了防止DFS死循环。

相较于上个宴会题,这道题很明显也没有什么前面的枝头剪去了,后面的状态也跟着变化之类的,没有。剪去了就剪去了,并没有什么状态。硬要说,就是我们选择花的时候需要选择大的花,也就是没有负数的花。那为什么不选择那些正数的大的呢?因为在树中,前后关系只要定下来就是固定的,我们只需要判断是不是选择这朵花就行了,因为这也就是一个二叉树的形式,并没有太多的枝头让我们选择。

上代码看看吧:

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath> 
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<deque>
#include <iomanip>
#include<sstream>
#include<numeric>
#include<map>
#include<limits.h>
#include<unordered_map>
#include<set>
#define int long long
#define MAX 20020
#define inf 0x3f3f3f3f
#define _for(i,a,b) for(int i=a;i<(b);i++)
using namespace std;
typedef pair<int, int> PII;
int n, m;
int counts;
int dx[] = { 0,1,0,-1};
int dy[] = { 1,0,-1,0 };
int w[MAX];
vector<int>vec[MAX];
int dp[MAX];
void dfs(int u,int fa) {
    dp[u] = w[u];
    _for(i, 0, vec[u].size()) {
        int son = vec[u][i];
        if (son == fa)continue;
        dfs(son, u);
        dp[u] += max((int)0, dp[son]);
    }
    return;
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    cin >> n;
    _for(i, 1, n + 1)
        cin >> w[i];
    _for(i, 1, n) {
        int x,y;
        cin >> x >> y;
        vec[y].push_back(x);
        vec[x].push_back(y);
    }
    dfs(1,0);
    int res = -inf;
    _for(i, 1, n + 1)
        res = max(res, dp[i]);
    cout << res;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值