本题的树上子链的说法是我第一次见,树上子链指的是树上的任意一条链,换句话说就是树上任意两点中最长的那一个。但这题不是以长度定的,每个节点都有权值,要的是权值和最长的子链。
所以我们对于某一个节点,选取儿子中最长和次长。然后加上节点本身就是答案了。
但在这里面寻找最长和次长的方式很巧妙,先贴代码:
res = max(res, dp[x]+dp[y]); dp[x] = max(dp[x], dp[y]+val[x]);在这里面先更新res,res是最终的结果。然后更新dp[x]是在寻找哪个加上本节点最大。那么在寻找过程中如果先找到最大值对于res的每次更新就可以将次大值算上。如果先找到的是次大值在更新过程中也可以算上。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e5+10;
int n;
vector<int> v[maxn];
int dp[maxn];
int val[maxn];
int res = INT_MIN;
void dfs(int x, int fa){
int len = v[x].size();
dp[x] = val[x];
for (int i=0;i<len;i++) {
int y = v[x][i];
if (y==fa) continue;
dfs(y, x);
res = max(res, dp[x]+dp[y]);
dp[x] = max(dp[x], dp[y]+val[x]);
}
res = max(res, dp[x]);
}
signed main() {
cin>>n;
int x, y;
for (int i=1;i<=n;i++) {
cin>>val[i];
}
for (int i=1;i<n;i++) {
cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1, 0);
cout<<res;
return 0;
}

京公网安备 11010502036488号