A. The Fair Nut and the Best Path

题意:给定有点权,有边权的树,让你选择一条链(也可以是只有一个点),使得点权之和-边权最大。

思路:裸的树形DP,我们用dp[i]表示i的子树里某个点到i这条链的最大值,然后用次大值更新答案即可。

具体的,每个dp[i]初始化=a[i];  对于i连出去的边-> (i,j),用它来更新答案,max(ans,dp[i]+dp[j]-len[i,j]);然后用它更新dp[i],max(dp[i],dp[i]-len[i,j]);

因为要的是最大值,肯定中途是大于等于0的,所以不会有中途油料耗尽的情况。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int maxn=1000010;
int a[maxn],Laxt[maxn],Next[maxn],To[maxn],Len[maxn],cnt;
ll dp[maxn],ans;
void add(int u,int v,int c)
{
    Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=c;
}
void dfs(int u,int f)
{
    dp[u]=a[u]; if(a[u]>ans) ans=a[u];
    for(int i=Laxt[u];i;i=Next[i]){
        int v=To[i]; if(v==f) continue;
        dfs(v,u);
        ans=max(ans,dp[u]+dp[v]-Len[i]);
        dp[u]=max(dp[u],dp[v]-Len[i]+a[u]);
    }
}
int main()
{
    int N,u,v,c;
    scanf("%d",&N);
    rep(i,1,N) scanf("%d",&a[i]);
    rep(i,1,N-1){
        scanf("%d%d%d",&u,&v,&c);
        add(u,v,c); add(v,u,c);
    }
    dfs(1,0);
    printf("%lld\n",ans);
    return 0;
}
View Code

相关文章: