这道题和宝藏差不多吧,转移的时候比较麻烦的。
代码中分量很多种情况。
h更新比较麻烦
这两幅图表示了双边更新中3,4连个h更新,下面比较好理解的吧。
1 #include<cstring> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdio> 6 #define N 307 7 using namespace std; 8 9 const int inf=1000000009; 10 11 int n,m,ans=-inf; 12 int w[N],t[N]; 13 int f[N][N],g[N][N],h[N][N]; 14 int cnt,head[N],next[N*2],rea[N*2],val[N*2]; 15 16 void add(int u,int v,int fee) 17 { 18 next[++cnt]=head[u],head[u]=cnt; 19 rea[cnt]=v,val[cnt]=fee; 20 } 21 void dfs(int u,int fa) 22 { 23 for (int i=0;i<=m;i++) 24 f[u][i]=g[u][i]=h[u][i]=(i>=t[u]?w[u]:-inf);//初始化 25 for (int i=head[u];i!=-1;i=next[i])//这次均摊是O(1) 26 { 27 int v=rea[i],fee=val[i]; 28 if (v==fa) continue; 29 dfs(v,u); 30 for (int j=m;j>=fee;j--) 31 for (int k=0;k<=j-fee;k++) 32 { 33 int nowf=f[u][j],nowg=g[u][j],nowh=h[u][j]; 34 if (j-2*fee-k>=0) 35 { 36 nowf=max(nowf,f[u][j-2*fee-k]+f[v][k]); 37 nowg=max(nowg,g[u][j-2*fee-k]+f[v][k]); 38 nowh=max(nowh,h[u][j-2*fee-k]+f[v][k]);//图上注释 39 nowh=max(nowh,f[u][j-2*fee-k]+h[v][k]);//图上注释 40 } 41 nowg=max(nowg,f[u][j-k-fee]+g[v][k]);//直接进入这个v结束 42 nowh=max(nowh,g[u][j-k-fee]+g[v][k]);//直接进入这个v结束 43 f[u][j]=nowf,g[u][j]=nowg,h[u][j]=nowh; 44 } 45 } 46 // cout<<u<<" "<<h[u][m]<<" "<<f[u][m]<<" "<<g[u][m]<<endl; 47 ans=max(ans,h[u][m]); 48 if (fa==-1) printf("%d",ans); 49 } 50 int main() 51 { 52 memset(head,-1,sizeof(head)); 53 scanf("%d%d",&n,&m); 54 for (int i=1;i<=n;i++) scanf("%d",&w[i]); 55 for (int i=1;i<=n;i++) scanf("%d",&t[i]); 56 for (int i=1,x,y,z;i<n;i++) 57 { 58 scanf("%d%d%d",&x,&y,&z); 59 add(x,y,z),add(y,x,z); 60 } 61 dfs(1,-1); 62 }
转移O(n^2),遍历O(n),然后就是O(n^3)