[hdu6201]transaction transaction transaction(树形dp)
题意:某人在一棵树中在某处买物品,价格为i,在某处卖物品,价格为j,每单位距离花费价格1,求最大赚钱数。
解题关键:两次树形dp,分别求出每个点作为被减和被加情况下的最大值,最后取一下max即可。
该节点被减的情况,为他和他所在的子树上的最大值,并且是他的各父节点的被减,该节点被加情况的最大值;
该节点被加的情况,为他和他所在的子树上的最大值,并且是他的各父节点的被加,该节点被减情况的最大值。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostream> 7 using namespace std; 8 typedef long long ll; 9 const int maxn=1e6+3; 10 const ll inf=1e17+3; 11 ll head[maxn],tot,n,m,sum,val[maxn]; 12 struct edge{ 13 ll to; 14 ll nxt; 15 ll w; 16 }e[maxn<<1]; 17 void add_edge(int u,int v,int w){ 18 e[tot].to=v; 19 e[tot].w=w; 20 e[tot].nxt=head[u]; 21 head[u]=tot++; 22 } 23 24 ll dp[maxn],cnt[maxn],ans,dp2[maxn]; 25 26 void dfs(ll u,ll fa){ 27 for(int i=head[u];i!=-1;i=e[i].nxt){ 28 int v=e[i].to; 29 int w=e[i].w; 30 if(v==fa) continue; 31 dfs(v,u); 32 dp[u]=max(dp[v]+val[v]-w-val[u],dp[u]); 33 dp2[u]=max(dp2[v]-val[v]-w+val[u],dp2[u]); 34 } 35 } 36 37 inline int read(){ 38 char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar()); 39 int x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0'; 40 if(k=='-')x=0-x;return x; 41 } 42 43 int main(){ 44 int k=0; 45 int T; 46 T=read(); 47 while(T--){ 48 n=read(); 49 memset(dp,0,sizeof dp); 50 memset(head,-1,sizeof head); 51 memset(dp2,0,sizeof dp2); 52 tot=0; 53 sum=0; 54 int a,b,c; 55 for(int i=1;i<=n;i++) val[i]=read(); 56 for(int i=0;i<n-1;i++){ 57 a=read(); 58 b=read(); 59 c=read(); 60 add_edge(a,b,c); 61 add_edge(b,a,c); 62 } 63 dfs(1,-1); 64 ll ans=-inf; 65 for(int i=1;i<=n;i++){ 66 ans=max(ans,dp[i]); 67 ans=max(ans,dp2[i]); 68 } 69 printf("%lld\n",ans); 70 } 71 return 0; 72 }