cf1084d 非常巧妙的树形dp
/* 给定n城市,m条道路,每条路耗油w,每个点有油a[i],从任意点出发,求最大可以剩下的油 dp[i]表示从i开始往下走的最大收益,ans表示最大结果 因为走过的路不能走,所以可以想到最优解肯定经过某个点u,其余点都是其子节点 并且即使有分叉,也一定在这个点u上 那么在dp时先处理好子节点,获得所有的dp[son],然后再更新dp[u]和ans即可 */ #include<bits/stdc++.h> using namespace std; #define maxn 300005 #define ll long long struct Edge{int to,nxt,w;}edge[maxn<<1]; int n,m,a[maxn],head[maxn],tot; void init(){ memset(head,-1,sizeof head); tot=0; } void addedge(int u,int v,int w){ edge[tot].w=w; edge[tot].to=v,edge[tot].nxt=head[u],head[u]=tot++; } ll dp[maxn],ans;// void dfs(int u,int pre){ dp[u]=a[u];ans=max(dp[u],ans); for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(v==pre)continue; dfs(v,u); ans=max(ans,dp[u]+dp[v]-edge[i].w);//前面的是dp[u]而不是a[i]表示可以承受一条岔路 dp[u]=max(dp[u],a[u]+dp[v]-edge[i].w);//根据dp[u]定义即可 } } int main(){ init(); cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<n;i++){ int u,v,w; cin>>u>>v>>w; addedge(v,u,w); addedge(u,v,w); } dfs(1,0); cout<<ans<<endl; }