暴力dp时间复杂度为$o(nm^{2})$,是不行的
考虑当我们强制该连通块包含根,可以直接在dfs序上dp,即若该点选则考虑从$f_{i+1}$转移,否则从其子树所对应区间右端点+1来转移(即$f_{dfn_{x}+sz_{x}}$),利用单调队列优化可做到$o(nm)$
之后对其点分治即可,时间复杂度为$o(nmlog_{2}n)$

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 505 4 #define M 4005 5 struct ji{ 6 int nex,to; 7 }edge[N<<1]; 8 deque<int>q[M]; 9 int E,t,n,m,r,x,y,ans,w[N],c[N],d[N],head[N],vis[N],sz[N],dfn[N],f[N][M]; 10 void add(int x,int y){ 11 edge[E].nex=head[x]; 12 edge[E].to=y; 13 head[x]=E++; 14 } 15 void tot(int k,int fa){ 16 sz[k]=1; 17 for(int i=head[k];i!=-1;i=edge[i].nex) 18 if ((!vis[edge[i].to])&&(edge[i].to!=fa)){ 19 tot(edge[i].to,k); 20 sz[k]+=sz[edge[i].to]; 21 } 22 } 23 void find(int k,int fa,int s){ 24 int mx=s-sz[k]; 25 for(int i=head[k];i!=-1;i=edge[i].nex) 26 if ((!vis[edge[i].to])&&(edge[i].to!=fa)){ 27 find(edge[i].to,k,s); 28 mx=max(mx,sz[edge[i].to]); 29 } 30 if (mx<=s/2)r=k; 31 } 32 void get_root(int k){ 33 tot(k,0); 34 find(k,0,sz[k]); 35 } 36 void dfs(int k,int fa){ 37 dfn[++dfn[0]]=k; 38 sz[k]=1; 39 for(int i=head[k];i!=-1;i=edge[i].nex) 40 if ((!vis[edge[i].to])&&(edge[i].to!=fa)){ 41 dfs(edge[i].to,k); 42 sz[k]+=sz[edge[i].to]; 43 } 44 } 45 void calc(int k){ 46 dfn[0]=0; 47 dfs(k,0); 48 for(int i=0;i<=m;i++)f[dfn[0]+1][i]=0; 49 for(int i=dfn[0];i;i--){ 50 int x=dfn[i]; 51 for(int j=0;j<=m;j++)f[i][j]=f[i+sz[x]][j]; 52 if (c[x]>m)continue; 53 for(int j=0;j<c[x];j++)q[j].clear(); 54 for(int j=0;j<=m;j++){ 55 int p=j%c[x]; 56 while ((!q[p].empty())&&(q[p].front()<j-d[x]*c[x]))q[p].pop_front(); 57 if (!q[p].empty()){ 58 int y=q[p].front(); 59 f[i][j]=max(f[i][j],f[i+1][y]+(j-y)/c[x]*w[x]); 60 } 61 while (!q[p].empty()){ 62 int y=q[p].back(); 63 if (f[i+1][y]+(j-y)/c[x]*w[x]>=f[i+1][j])break; 64 q[p].pop_back(); 65 } 66 q[p].push_back(j); 67 } 68 } 69 ans=max(ans,f[1][m]); 70 } 71 void dfs(int k){ 72 if (vis[k])return; 73 get_root(k); 74 calc(r); 75 vis[r]=1; 76 for(int i=head[r];i!=-1;i=edge[i].nex)dfs(edge[i].to); 77 } 78 int main(){ 79 scanf("%d",&t); 80 while (t--){ 81 scanf("%d%d",&n,&m); 82 for(int i=1;i<=n;i++)scanf("%d",&w[i]); 83 for(int i=1;i<=n;i++)scanf("%d",&c[i]); 84 for(int i=1;i<=n;i++)scanf("%d",&d[i]); 85 E=ans=0; 86 memset(head,-1,sizeof(head)); 87 for(int i=1;i<n;i++){ 88 scanf("%d%d",&x,&y); 89 add(x,y); 90 add(y,x); 91 } 92 memset(vis,0,sizeof(vis)); 93 dfs(1); 94 printf("%d ",ans); 95 } 96 }