题目链接:Codeforces - The Fair Nut and the Best Path
找一条权值最大的链。
显然我们可以树dp,dp[x][0/1]分别表示,最长路径在子树当中,最长路径一个点在子树当中,一个点在子树之外。然后就可以转移了。
每次找最大值和次大值。
dp[x][0]=a[x]+max
dp[x][1]=a[x]+max+max_s
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10,M=N<<1;
int n,a[N],dp[N][2],res;
int head[N],nex[M],to[M],w[M],tot;
inline void ade(int a,int b,int c){
to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot;
}
inline void add(int a,int b,int c){ade(a,b,c); ade(b,a,c);}
void dfs(int x,int fa){
int mx1=0,mx2=0;
for(int i=head[x];i;i=nex[i]) if(to[i]!=fa){
dfs(to[i],x);
if(dp[to[i]][0]-w[i]>mx1) mx2=mx1,mx1=dp[to[i]][0]-w[i];
else if(dp[to[i]][0]-w[i]>mx2) mx2=dp[to[i]][0]-w[i];
}
dp[x][0]=a[x]+mx1;
dp[x][1]=a[x]+mx1+mx2;
res=max(res,max(dp[x][0],dp[x][1]));
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1,a,b,c;i<n;i++) scanf("%lld %lld %lld",&a,&b,&c),add(a,b,c);
dfs(1,1);
cout<<res;
return 0;
}