题目大意:
给定一棵树 树上每个点有对应的点权
树上每条边有对应的边权
经过一个点可得到点权 经过一条边必须花费边权
即从u到v 最终得分=u的点权-u到v的边权+v的点权
求树上一条路径使得得分最大
看注释
#include <bits/stdc++.h> #define LL long long #define INf 0x3f3f3f3f using namespace std; const int N=3e5+5; bool vis[N]; LL w[N], ans; int n; struct NODE { int to,nt; LL l; }e[N<<1]; int head[N], tot; void addE(int u,int v,LL l) { e[tot].to=v, e[tot].l=l; e[tot].nt=head[u]; head[u]=tot++; } void init() { memset(head,0,sizeof(head)); tot=1; } LL dfs(int u,int fa) { vis[u]=1; LL ans1=0LL, ans2=0LL; // ans1由子节点出发的一条路径最大得分 ans2为次大 for(int i=head[u];i;i=e[i].nt) { int v=e[i].to; if(v==fa || vis[v]) continue; LL tmp=dfs(v,u)-e[i].l; if(tmp>ans1) swap(tmp,ans1); if(tmp>ans2) swap(tmp,ans2); } ans=max(ans,ans1+ans2+w[u]); // 可由最大得分和次大得分加上u点 得到一条经过u点的路径的最大得分 return ans1+w[u]; // 只返回由u出发的一条路径可得到的最大得分 } int main() { while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) scanf("%I64d",&w[i]); init(); for(int i=1;i<n;i++) { int u,v; LL l; scanf("%d%d%I64d",&u,&v,&l); addE(u,v,l); addE(v,u,l); } memset(vis,0,sizeof(vis)); ans=0LL; dfs(1,0); printf("%I64d ",ans); } return 0; }