题解:P13680 [IAMOI R2] 未送出的花
思路
考虑盛开度已经确定后,对于一个点
同上,考虑一种情况,盛开度
于是有性质,父节点盛开度大于子节点盛开度更优。据此,如果一个节点深度为
我们可以知道每个点的盛开度确定多少个点的美丽度,题目相当于求与点
树上背包即可,令
code
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
inline int read(){
int x=0,f=1;char ch=getchar();
while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,p[N],siz[N],son[N],F[N],f[N][N];
int head[N],vi[N<<1],nxt[N<<1],tot;
inline void add(int u,int v){
vi[++tot]=v;nxt[tot]=head[u];head[u]=tot;
vi[++tot]=u;nxt[tot]=head[v];head[v]=tot;
return;
}
inline void dfs(int u,int fa,int dep){
p[dep]=u;
son[p[dep/2]]++;
for(int i=head[u];i;i=nxt[i]){
int v=vi[i];
if(v==fa)continue;
dfs(v,u,dep+1);
}
return;
}
inline void dp(int u,int fa){
siz[u]=1;
f[u][1]=son[u];
for(int i=head[u];i;i=nxt[i]){
int v=vi[i];
if(v==fa)continue;
dp(v,u);
for(int j=siz[u]+siz[v];j>siz[u];j--)f[u][j]=0;
for(int j=1;j<=siz[u];j++)F[j]=f[u][j];
for(int j=1;j<=siz[u];j++)
for(int k=1;k<=siz[v];k++)
f[u][j+k]=max(f[u][j+k],F[j]+f[v][k]);
siz[u]+=siz[v];
}
}
inline void solve(){
n=read();
tot=0;
for(int i=1;i<=n;i++)
head[i]=son[i]=0;
for(int i=1;i<n;i++)add(read(),read());
dfs(1,0,0);
dp(1,0);
for(int i=1;i<=siz[1];i++)
for(int j=f[1][i-1]+1;j<=f[1][i];j++)
printf("%d ",n-i+1);
puts("");
return;
}
int main(){
// freopen("c.in","r",stdin);
// freopen("c.out","w",stdout);
int t=read();
while(t--)solve();
return 0;
}