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