思路:树形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;
}