transaction transaction transaction HDU - 6201(树上dp)
【题意】
给出一棵生成树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过所需要的花费。
现在需要你在树上选择两个点,一个作为买入商品的点,一个作为卖出商品的点,当然需要考虑从买入点到卖出点经过边的花费。使得收益最大。
允许买入点和卖出点重合,即收益最小值为0.
【思路】
我的方法:从根到当前节点记录最少成本,再从叶子节点到当前节点记录最少的成本和最高的收入,得出该点在该子树上的最高利润。
#include <cstdio> #include <iostream> #include <cstring> using namespace std; const int maxn=1e5+10; int buy[maxn],sale[maxn]; int head[maxn<<1],id[maxn<<1],nt[maxn<<1],wt[maxn<<1],cnt; int n,p[maxn]; void init() { memset(head,-1,sizeof(head)); cnt=0; } void add(int x,int y,int w) { id[cnt]=y; nt[cnt]=head[x]; wt[cnt]=w; head[x]=cnt++; } int dfs(int u,int pre,int b) { buy[u]=sale[u]=p[u]; int ret=p[u]-b; for(int i=head[u];i!=-1;i=nt[i]) { int v=id[i],w=wt[i]; if(v==pre) continue; ret=max(ret,dfs(v,u,min(b+w,p[u]+w))); buy[u]=min(buy[v]+w,buy[u]); sale[u]=max(sale[v]-w,sale[u]); } return max(ret,(sale[u]-buy[u])); } int main() { int t; cin>>t; while(t--) { init(); int n; cin>>n; for(int i=1;i<=n;i++) scanf("%d",p+i); for(int i=1;i<n;i++) { int x,y,w; scanf("%d%d%d",&x,&y,&w); add(x,y,w); add(y,x,w); } int ans=dfs(1,0,10001); cout<<ans<<endl; } }
大佬方法:
我们设1为根节点,假设一开始一个人身上的钱为0。
我们设dp[i][0]表示从i及其子树并中任一点买入一本书并走到i点后这个人身上钱的最大值(显然是负的)。
dp[i][1]表示从i及其子树并中任一点卖出一本书并走到i点后这个人身上钱的最大值(可正可负)。
那么我们对这棵树进行一次树形DP即可,dfs后对每个节点更新收益最大值,单点的计算方法为
w=dp[i][0]+dp[i][1]
(由于前者是负的,相当于收入减去总花费)
对比我的方法,直接从叶子节点收束就行了,已经包含了靠近根节点的买,远离的卖的情况,不需要再从根节点往下传参数了。
#include <cstdio> #include <vector> #include <cstring> #include <algorithm> using namespace std; #define mst(a,b) memset((a),(b),sizeof(a)) #define rush() int T;scanf("%d",&T);while(T--) typedef long long ll; const int maxn = 100005; const ll mod = 1e9+7; const int INF = 0x3f3f3f3f; const double eps = 1e-6; struct node { int v,w; node(int _v,int _w):v(_v),w(_w) {} }; int n,ans; int val[maxn]; int dp[maxn][2]; vector<node>vec[maxn]; void dfs(int u,int pre) { dp[u][0]=-val[u]; dp[u][1]=val[u]; for(int i=0;i<vec[u].size();i++) { int v=vec[u][i].v; int w=vec[u][i].w; if(v==pre) continue; dfs(v,u); dp[u][0]=max(dp[u][0],dp[v][0]-w); dp[u][1]=max(dp[u][1],dp[v][1]-w); } ans=max(ans,dp[u][0]+dp[u][1]); } int main() { int u,v,w; rush() { scanf("%d",&n); for(int i=0;i<=n;i++) { vec[i].clear(); } for(int i=1;i<=n;i++) { scanf("%d",&val[i]); } for(int i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&w); vec[u].push_back(node(v,w)); vec[v].push_back(node(u,w)); } ans=0; dfs(1,-1); printf("%d\n",ans); } return 0; }

浙公网安备 33010602011771号