题意:给出一个树,然后每个点都有相应的权值,点与点之间有相应的边权,只能跑树上的简单路径,也就是每个点只能经过一次,最后经过路径落下的值最大能是多少,经过点加上点权,经过边,减去边权。
题解:树形DP,dp[u][0]表示经过u这个点的一个子边所能达到的最大值,也就是起点是儿子,终点是u,dp[u][1]表示经过了u,也就是起点和终点分别是儿子,这个dp[u][1]先维护dp[u][0]的次大值即可,然后最后两者相加时把中间多加的减下即可。
友情提示:爆int
附上代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+5;
int n,a[maxn];
ll dp[maxn][2];
struct data{int v,w,next;}e[maxn*2];
int head[maxn],tot;
void add_edge(int u,int v,int w)
{
e[++tot].v=v;e[tot].w=w;e[tot].next=head[u];head[u]=tot;
e[++tot].v=u;e[tot].w=w;e[tot].next=head[v];head[v]=tot;
}
ll ans=0;
void dfs(int u,int fa)
{
dp[u][0]=a[u];
ans=max(ans,dp[u][0]);
for(int i=head[u];i;i=e[i].next){
if(e[i].v==fa)continue;
dfs(e[i].v,u);
bool flag=false;
if(a[u]+dp[e[i].v][0]-e[i].w>dp[u][0]){
dp[u][1]=dp[u][0];
dp[u][0]=a[u]+dp[e[i].v][0]-e[i].w;
flag=true;
}
if(!flag){
if(a[u]+dp[e[i].v][0]-e[i].w>dp[u][1]){
dp[u][1]=a[u]+dp[e[i].v][0]-e[i].w;
}
}
if(dp[u][1]){
ans=max(ans,dp[u][1]+dp[u][0]-a[u]);
}
ans=max(ans,dp[u][0]);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int u,v,w;
for(int i=1;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
}
dfs(1,-1);
printf("%lld\n",ans);
return 0;
}