题解:P4845 LJJ 爱数树
考虑 dp,设
转移类似背包的转移。
若
跟上面是类似的。
直接转移
直接转移
直接暴力做是
具体的实现可以看代码,代码注释即为暴力转移。
#include<bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
inline int read(){char c=getchar();int f=1,ans=0;while(c<48||c>57) f=(c==45?f=-1:1),c=getchar();while(c>=48&&c<=57) ans=(ans<<1)+(ans<<3)+(c^48),c=getchar();return ans*f;}
const int N=1e3+10,inf=1e18;
vector<vector<int>>f[N],g[N],pref[N],preg[N],suff[N],sufg[N];
vector<int>a[N];
int sz[N],n,k,r,w[N];
inline void chk(int &x,int y){x=(x>y?x:y);}
void dfs(int u,int fa){
sz[u]=1;
f[u].resize(2,vector<int>(r+2,-inf)),g[u].resize(2,vector<int>(r+2,-inf));
f[u][0][r+1]=0,f[u][1][0]=w[u],g[u][0][0]=w[u];pref[u]=f[u],preg[u]=g[u],suff[u]=f[u],sufg[u]=g[u];
for (int i=0;i<2;i++) for (int j=1;j<=r+1;j++) chk(pref[u][i][j],pref[u][i][j-1]);
for (int i=0;i<2;i++) for (int j=1;j<=r;j++) chk(preg[u][i][j],preg[u][i][j-1]);
for (int i=0;i<2;i++) for (int j=r;j>=0;j--) chk(suff[u][i][j],suff[u][i][j+1]);
for (int i=0;i<2;i++) for (int j=r-1;j>=0;j--) chk(sufg[u][i][j],sufg[u][i][j+1]);
for (auto v:a[u]) if (v^fa){
dfs(v,u);
vector<vector<int>>tmpf(min(sz[u]+sz[v],k)+1,vector<int>(r+2,-inf)),tmpg(min(sz[u]+sz[v],k)+1,vector<int>(r+2,-inf));
for (int i=0;i<=min(sz[u],k);i++) for (int j=0;j<=min(sz[v],k);j++) if (i+j<=k){
/* // f+g
for (int x=0;x<=r+1;x++) for (int y=0;y<=r;y++){
if (x+y+1<=r) chk(tmpf[i+j][x],f[u][i][x]+g[v][j][y]);
else chk(tmpg[i+j][y+1],f[u][i][x]+g[v][j][y]);
}
// g+f
for (int x=0;x<=r;x++) for (int y=0;y<=r+1;y++){
if (x+y+1<=r) chk(tmpf[i+j][y+1],g[u][i][x]+f[v][j][y]);
else chk(tmpg[i+j][x],g[u][i][x]+f[v][j][y]);
}
// f+f
for (int x=0;x<=r+1;x++) for (int y=0;y<=r+1;y++)
chk(tmpf[i+j][min(x,y+1)],f[u][i][x]+f[v][j][y]);
// g+g
for (int x=0;x<=r;x++) for (int y=0;y<=r;y++)
chk(tmpg[i+j][max(x,y+1)],g[u][i][x]+g[v][j][y]); */
for (int x=0;x<=r;x++){
if (r-1-x>=0) chk(tmpf[i+j][x],f[u][i][x]+preg[v][j][r-1-x]);
if (r-x<=r+1) chk(tmpg[i+j][x+1],suff[u][i][max(0ll,r-x)]+g[v][j][x]);
}
for (int x=0;x<=r;x++){
if (r-x-1>=0) chk(tmpf[i+j][x+1],preg[u][i][r-x-1]+f[v][j][x]);
if (r-x<=r) chk(tmpg[i+j][x],g[u][i][x]+suff[v][j][max(0ll,r-x)]);
}
for (int x=0;x<=r+1;x++){
chk(tmpf[i+j][x],f[u][i][x]+suff[v][j][max(0ll,x-1)]);
if (x+1<=r+1) chk(tmpf[i+j][x+1],suff[u][i][x+1]+f[v][j][x]);
}
for (int x=0;x<=r;x++){
if (x-1>=0) chk(tmpg[i+j][x],g[u][i][x]+preg[v][j][x-1]);
chk(tmpg[i+j][x+1],preg[u][i][min(r+1,x+1)]+g[v][j][x]);
}
}
f[u]=pref[u]=suff[u]=tmpf,g[u]=preg[u]=sufg[u]=tmpg;
for (int i=0;i<=min(sz[u]+sz[v],k);i++) for (int j=1;j<=r+1;j++) chk(pref[u][i][j],pref[u][i][j-1]);
for (int i=0;i<=min(sz[u]+sz[v],k);i++) for (int j=1;j<=r;j++) chk(preg[u][i][j],preg[u][i][j-1]);
for (int i=0;i<=min(sz[u]+sz[v],k);i++) for (int j=r;j>=0;j--) chk(suff[u][i][j],suff[u][i][j+1]);
for (int i=0;i<=min(sz[u]+sz[v],k);i++) for (int j=r-1;j>=0;j--) chk(sufg[u][i][j],sufg[u][i][j+1]);
sz[u]+=sz[v];
}
}
inline void solve(){
n=read(),k=read(),r=read();
for (int i=1;i<=n;i++) a[i].clear(),w[i]=read(),f[i].clear(),g[i].clear(),pref[i].clear(),preg[i].clear();
for (int i=1,u,v;i<n;i++) u=read(),v=read(),a[u].push_back(v),a[v].push_back(u);
if (k*r>=n){int ans=0;for (int i=1;i<=n;i++) ans+=w[i];return printf("%lld\n",ans),void();}
dfs(1,0);
int ans=0;for (int i=0;i<=min(sz[1],k);i++) for (int j=0;j<=r+1;j++) chk(ans,f[1][i][j]);
printf("%lld\n",ans);
}
main(){
int T=read();
while(T--) solve();
return 0;
}