D. The Fair Nut and the Best Path
https://codeforces.com/contest/1084/problem/D?tdsourcetag=s_pctim_aiomsg
题意:一个树,点有值,边有值,求任意两点之间的最大值,遇到点要加它对应的值,遇到边减掉它对应的值。
思路:嗯,题意理解做法水的一笔,任意两点的路径的最大值,可以采用dfs,回溯到父亲结点,与它两个较大的(可能一个或零个)子节点的路径构成最大路径。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=6e5+10;
ll f[maxn];
int val[maxn];
int head[maxn],nxt[maxn],ver[maxn];
ll edge[maxn];
int tot=0;
void add(int u,int v,ll w)
{
ver[++tot]=v;
edge[tot]=w;
nxt[tot]=head[u];
head[u]=tot;
}
ll ans=0;
void dfs(int u,int fa)
{
ll maxx1=0;
ll maxx2=0;
for(int i=head[u]; i; i=nxt[i])
{
int v=ver[i];
ll w=edge[i];
if(v==fa) continue;
dfs(v,u);
if((f[v]+w)>=maxx1)
{
maxx2=maxx1;
maxx1=f[v]+w;
}
else if((f[v]+w)>maxx2)
maxx2=f[v]+w;
}
ans=max(ans,maxx1+maxx2+val[u]);
f[u]=val[u]+maxx1;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&val[i]);
for(int i=1; i<=n-1; i++)
{
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
add(u,v,-w);
add(v,u,-w);
}
dfs(1,0);
printf("%lld",ans);
}