Codeforces Round #526 (Div. 2) D. The Fair Nut and the Best Path 樹上dp
阿新 • • 發佈:2019-05-01
push ret 起點 air and second eof The bit 表示以i的權值 加 以i為起點的路徑的最大的兩條可以獲得的權值
D. The Fair Nut and the Best Path
題意:給出一張圖 點有權值 邊也要權值 從任意點出發到任意點結束 到每個點的時候都可以獲得每個點的權值,而從邊走的時候都要消耗改邊的邊權,如果當前值小於邊的邊權,就走不通,問從任意點出發到任意點結束的可以獲得的最大權多少(其中到一個點結束的時候也能獲得改點的值)
思路:一個很明顯的樹上dp的問題 \(dp[i]\)表示以i為起點的可以獲得的最高的權值是多少
\(dp[i]=w[i]+max(son(dp[j]))\) 其中j為i的兒子節點
表示的是以i為起點得到的最大權 通過以其兒子位起點的最大權來更新
而答案等於 \(max(w[i]+firstmax+secondmax)\)
#include<bits/stdc++.h> #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++) #define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr)) #define F first #define S second #define pii pair<int ,int > #define mkp make_pair #define pb push_back #define arr(zzz) array<ll,zzz> using namespace std; typedef long long ll; #define int ll const int maxn=3e5+5; struct Node{ int to,next,value; }edge[maxn*10]; int head[maxn],w[maxn]; int dp[maxn]; int size=0; ll ans=0; void add(int x,int y,int v){ edge[size].to=y; edge[size].next=head[x]; edge[size].value=v; head[x]=size++; } void dfs(int now,int fa){ dp[now]+=w[now]; //cout<<dp[now]<<" "<<now<<endl; ll firstmax=0,secondmax=0; for(int i=head[now];i!=-1;i=edge[i].next){ int y=edge[i].to; int v=edge[i].value; if(y!=fa){ dfs(y,now); if(dp[y]-v>=firstmax){ secondmax=firstmax; firstmax=dp[y]-v; } else if(dp[y]-v>secondmax){ secondmax=dp[y]-v; } } //cout<<dp[now]<<" "<<firstmax<<" "<<secondmax<<" "<<now<<" "<<endl; //dp[now]+=firstmax; } ans=max(ans,dp[now]+secondmax+firstmax); dp[now]+=firstmax; //cout<<dp[now]<<" "<<w[now]<<" "<<ans<<" "<<firstmax<<" "<<secondmax<<" "<<now<<endl; } int32_t main(){ int n; memset(head,-1,sizeof(head)); scanf("%lld",&n); for(int i=1;i<=n;i++){ scanf("%lld",&w[i]); } int x,y,v; for(int i=1;i<n;i++) { scanf("%lld%lld%lld",&x,&y,&v); add(x,y,v); add(y,x,v); } dfs(1,-1); cout<<ans<<endl; return 0; }
Codeforces Round #526 (Div. 2) D. The Fair Nut and the Best Path 樹上dp