题意
在树上不同的点,一个物品价值不同,可任选一个点为起点,买进此物品,再找出卖出此物品能得到的最大价值。通往其他点需要耗费边权大小的费用
分析
先开始想考虑一维状态就定义完,但是发现不好做。
定义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; }