CF1083A The Fair Nut and the Best Path 题解

CF1083A The Fair Nut and the Best Path 题解

CF1083A

题意

给定一棵树,经过边时会损失边权大小的收益,经过点时会增加点权大小的收益。问一条路径的最大收益。

分析

很容易想到树形 dp。对于每个点而言,以它作为中转点的最优收益是一条进入它的最优的链的收益加上从它走出的和走入那条链完全没有交点的最优的链的收益。

首先 dfs 一下,\(f_u\) 表示到达结点 \(u\) 的最大收益,对于子结点 \(v\) ,如果 \(f_v\) 减去连接 \(u,v\) 边的边权为负数,说明不合法。\(f_u=a_u+\max(f_v)\) ,其中 \(a_u\) 表示 \(u\) 的点权,记录从哪里转移的,记为 \(p_u\)

然后再 dfs 一遍,\(dp_u\) 表示以结点 \(u\) 作为中转点的链的最大收益,对于子结点 \(v\) ,如果 \(f_v\) 减去连接 \(u,v\) 的边权再加上 \(f_u\) 为负数,说明不合法。\(dp_u=f_u+\max(f_v)\ (v \neq p[u])\)

最后输出 \(\max(dp_i)\) 即可。

代码

#include <bits/stdc++.h>
#define int long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> Pair;
const int inf=2139062143;
inline void qread(){}template<class T1,class ...T2>
inline void qread(T1 &a,T2&... b)
{
    register T1 x=0;register bool f=false;char ch=getchar();
    while(ch<'0') f|=(ch=='-'),ch=getchar();
    while(ch>='0') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    x=(f?-x:x);a=x;qread(b...);
}
template<class T> T qmax(T x,T y){return x>y?x:y;}
template<class T,class ...Arg> T qmax(T x,T y,Arg ...arg){return qmax(x>y?x:y,arg...);}
template<class T> T qmin(T x,T y){return x<y?x:y;}
template<class T,class ...Arg> T qmin(T x,T y,Arg ...arg){return qmin(x<y?x:y,arg...);}
const int MAXN=3e5+7;
int n,dp[MAXN],a[MAXN],ans,f[MAXN],p[MAXN];
vector<Pair>tree[MAXN];
void dfs(int u,int fa)
{
    int mx=0;f[u]=a[u];
    for(auto v:tree[u])
    {
        if(fa==v.first) continue;
        dfs(v.first,u);
        if(f[v.first]-v.second<0) continue; // 只要路径上一个时刻的收益为负数就不合法
        if(f[v.first]-v.second>mx)
        {
            mx=f[v.first]-v.second; // 更新f值
            p[u]=v.first; // 记录路径
        }
    }f[u]+=mx;
}
void dfs1(int u,int fa)
{
    int mx=0;dp[u]=f[u];
    for(auto v:tree[u])
    {
        if(fa==v.first) continue;
        dfs1(v.first,u);
        if(v.first==p[u]) continue; // 不能走回头路
        if(f[u]+f[v.first]-v.second<0) continue; // 不合法
        mx=qmax(mx,f[v.first]-v.second);
    }dp[u]+=mx;
}
signed main()
{
    qread(n);int i,j;for(i=1;i<=n;i++) qread(a[i]);
    for(i=0;i<n-1;i++)
    {
        int u,v,w;qread(u,v,w);
        tree[u].push_back(Pair(v,w));
        tree[v].push_back(Pair(u,w));
    }dfs(1,-1);dfs1(1,-1);
    for(i=1;i<=n;i++) ans=qmax(ans,dp[i]);printf("%lld\n",ans);
    return 0;
}
posted @ 2022-03-21 18:13  l_x_y  阅读(41)  评论(0编辑  收藏  举报