题意
- 一颗有n个结点的树,每个结点具有权值,求解最长(权值最大)的一条子链
思路
- 对于某一个结点来思考,他能构成的最长子链无非下列集中情况之一
- 包含他的最长链+最长的包含他一个儿子的最长链
- 所有结点均为负值,最长子链自身的权值
- 他自己的一条最长链(另一条全负)
- 因此我们维护一个dp数组,dp[i]表示包含结点i的最长子链,u是i的儿子,最终的
为了避免dp[i]和dp[u]包含同一条子链,我们选择先更新res后更新dp[i],由因为存在全负的可能性,所以每次遍历一颗子树时,ans的初值应该取到dp[i]
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[202020],dp[202020];
int res=-0x3f3f3f3f;
vector<int> t[202020];
void dfs(int x,int fa){
dp[x]=a[x];
res=max(res,dp[x]);
for(auto i:t[x]){
if(i==fa) continue;
dfs(i,x);
res=max(res,dp[x]+dp[i]);
dp[x]=max(dp[x],dp[i]+a[x]);
}
}
signed main(){
int n;
cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
}
for(int i=1;i<n;i++){
int x,y;
cin >> x >> y ;
t[x].push_back(y);
t[y].push_back(x);
}
dfs(1,0);
cout << res << endl;
return 0;
}