标签:
/*
dp【s】【i】代表以s为根的剩余的为i个子节点的所需要删除最小的边数
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 155
#define inf 0x3f3f3f3f
int dp[N][N];
int b[N];
int a[N];
int root;
int vis[N];
int son[N];
int n,p;
//思路就是一层一层的搜下去
void dfs(int s){
dp[s][1]=0;//只剩余一个点的话 不需要删除边
int k=son[s];
while(k){
dfs(k);
for(int i=p;i>0;i--){
int tmp = dp[s][i]+1;//如果删除了i节点 那么只需要+1
for (int j = 1; j < i; ++ j)
{
if (dp[k][i - j] + dp[s][j] < tmp)//如果不删除的话,那么要判断k的子树是否存在删除变更少的边的可能
{
tmp = dp[k][i - j] + dp[s][j];
}
}
dp[s][i]=tmp;
}
k=b[k];//继续从他的兄弟
}
}
int main(){
while(scanf("%d%d",&n,&p)==2){
memset(dp,inf,sizeof(dp));
memset(son,0,sizeof(son));
memset(vis,0,sizeof(vis));
for(int i=1;i<n;i++){
int s, t;
scanf("%d%d",&s,&t);
b[t]=son[s];//他的兄弟是当前s的儿子
vis[t]=1;
son[s]=t;//把它设为当前的儿子
}
for(int i=1;i<=n;i++){
if(!vis[i]){
root = i;
break;
}
}
//printf("root = %d\n",root);
dfs(root);
int ans = dp[root][p];
for(int i=1;i<=n;i++){
if(ans>dp[i][p]+1){
ans=dp[i][p]+1;
}
}
printf("%d\n",ans);
}
}
标签:
原文地址:http://blog.csdn.net/u013076044/article/details/45822795