【HDU6201】transaction transaction transaction

题意

在树上不同的点,一个物品价值不同,可任选一个点为起点,买进此物品,再找出卖出此物品能得到的最大价值。通往其他点需要耗费边权大小的费用

分析

先开始想考虑一维状态就定义完,但是发现不好做。

定义f[u][0]表示以u为根的子树的最小成本,f[u][1]表示以u为根的子树的最大收入

从叶节点往上更新,对于每次访问到的节点贪心求答案。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long 
#define N 200010
ll t,n,cnt;
ll first[N];
ll ans;
ll f[N][2],val[N];
struct email
{
    ll u,v;
    ll w;
    ll nxt;
}e[N*4];
inline void add(ll u,ll v,ll w)
{
    e[++cnt].nxt=first[u];first[u]=cnt;
    e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;
}

inline void init()
{
    cnt=ans=0;
    memset(f,0,sizeof(f));
    memset(first,0,sizeof(first));
}

void dfs(ll u,ll fa)
{
    f[u][1]=f[u][0]=val[u];
    for(ll i=first[u];i;i=e[i].nxt)
    {
        ll v=e[i].v,w=e[i].w;
        if(v==fa)continue;
        dfs(v,u);
        f[u][0]=min(f[u][0],f[v][0]+w);
        f[u][1]=max(f[u][1],f[v][1]-w);
    }
    ans=max(ans,f[u][1]-f[u][0]);
}
int main()
{
    scanf("%lld",&t);
    while(t--)
    {
        init();
        scanf("%lld",&n);
        for(ll i=1;i<=n;i++)scanf("%lld",&val[i]);
        for(ll i=1;i<n;i++)
        {
            ll u,v,w;
            scanf("%lld%lld%lld",&u,&v,&w);
            add(u,v,w);add(v,u,w);
        }
        dfs(1,0);
        printf("%lld
",ans);
    }
    return 0;
}
“Make my parents proud,and impress the girl I like.”
原文地址:https://www.cnblogs.com/NSD-email0820/p/9764254.html