本题的树上子链的说法是我第一次见,树上子链指的是树上的任意一条链,换句话说就是树上任意两点中最长的那一个。但这题不是以长度定的,每个节点都有权值,要的是权值和最长的子链。
所以我们对于某一个节点,选取儿子中最长和次长。然后加上节点本身就是答案了。
但在这里面寻找最长和次长的方式很巧妙,先贴代码:
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;
}