Codeforces Round #526 D - The Fair Nut and the Best Path /// 樹上兩點間路徑花費
阿新 • • 發佈:2018-12-11
題目大意:
給定一棵樹 樹上每個點有對應的點權
樹上每條邊有對應的邊權
經過一個點可得到點權 經過一條邊必須花費邊權
即從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\n",ans); } return 0; }