传送门:http://codeforces.com/contest/1084/problem/D
题意:给出一棵树,点为正权,边为负权,找出一条简单路径,权和最大。
题解:我们定义g[i]代表以i结点为终点,从子树的点上来能获得的最大权值,那么同时要考虑i为转折点,那么只要在子树中找最大和次大的权和即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll w[300005],ans,dp[300005][2],g[300005];
int head[300005],cnt;
struct node{
int to,nex;
ll val;
}edge[600005];
void add(int u,int v,ll w){
edge[cnt].to=v;
edge[cnt].nex=head[u];
edge[cnt].val=w;
head[u]=cnt++;
}
void dfs(int t,int f){
g[t]=w[t];
for(int i=head[t];~i;i=edge[i].nex){
int v=edge[i].to;
if(v==f)continue;
dfs(v,t);
ll now=edge[i].val+g[v];
if(now>dp[t][0])swap(now,dp[t][0]);
if(now>dp[t][1])swap(now,dp[t][1]);
g[t]=max(g[t],g[v]+edge[i].val+w[t]);
}
ans=max(ans,g[t]);
ans=max(ans,w[t]+dp[t][0]+dp[t][1]);
}
int main(){
int n;
memset(head,-1,sizeof(head));
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lld",&w[i]);
for(int i=1;i<n;i++){
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
add(u,v,-w);
add(v,u,-w);
}
dfs(1,1);
printf("%lld\n",ans);
return 0;
}