知道树形dp肯定是节点与它的子节点的方程
想到dp[i][j]记录的是“以i节点为根”(不仅仅是包含i节点)的子树包含j个点的答案
刚开始没想到要以i节点为根记录状态,始终联想不到它和子节点的关系
然后被坑到的是这是一棵有根树,边是有向的!!
偷来的代码,构造的好简洁啊!!orz……很好的解决了初始化问题
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include <set>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
using namespace std;
#define N 155
#define INF 10000
int n,p;
int dp[N][N],subtree[N];
vector<int>vec[N];
void dfs(int u)
{
for(int i=0;i<vec[u].size();++i)
dfs(vec[u][i]);
dp[u][1]=vec[u].size();
for(int i=0;i<vec[u].size();++i)
{
int v=vec[u][i];
for(int j=p-1;j>=1;--j)
for(int k=1;j+k<=p;++k)
dp[u][j+k]=min(dp[u][j+k],dp[u][j]+dp[v][k]-1);
}
}
int solve()
{
for(int i=1;i<=n;++i)
for(int j=1;j<n;++j)
dp[i][j]=INF;
dfs(1);
int ret=INF;
for(int i=2;i<=n;++i)
ret=min(ret,dp[i][p]+1);
ret=min(ret,dp[1][p]);
return ret;
}
int main ()
{
while(scanf("%d%d",&n,&p)!=EOF)
{
for(int i=1;i<=n;++i)
vec[i].clear();
int u,v;
for(int i=1;i<n;++i)
{
scanf("%d%d",&u,&v);
vec[u].push_back(v);
}
int ans=solve();
printf("%d\n",ans);
}
return 0;
}