1. 程式人生 > >Codeforces Round #526 D - The Fair Nut and the Best Path /// 樹上兩點間路徑花費

Codeforces Round #526 D - The Fair Nut and the Best Path /// 樹上兩點間路徑花費

題目大意:

給定一棵樹 樹上每個點有對應的點權

樹上每條邊有對應的邊權

經過一個點可得到點權 經過一條邊必須花費邊權

即從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; }