这个题我们注意一下树上背包的dp表达形式。
此题巧妙地是,我们通过子树来计算根节点划分成大小为k的子树的方案。
我们设表示对于第个新儿子时,以为根节点,分离出大小为的子树的删减边的最小数目。
那么显然对于任意一个,我们有
显然第一维可以省掉,因此我们可以写出
得到代码。
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#define maxn 210
using namespace std;
int n,p;
vector<int> vec[maxn];
int deg[maxn];
int dp[maxn][maxn];
int ans=0x3f3f3f;
int dfs(int u, int fa)
{
dp[u][1]=deg[u];
for(int i=0;i<vec[u].size();i++)
{
int v = vec[u][i];
if(v == fa) continue;
dfs(v, u);
for(int i = p;i >= 1; i--)
for(int j = 1;j <= i; j++)
dp[u][i] = min(dp[u][i], dp[u][j] + dp[v][i-j] -2 );
}
ans=min(ans,dp[u][p]);
}
int main()
{
//freopen("testdata (3).in","r",stdin);
cin>>n>>p;
memset(dp, 0x3f, sizeof(dp));
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
vec[u].push_back(v);
vec[v].push_back(u);
deg[u]++;
deg[v]++;
}
dfs(1, 0);
cout<<ans;
}