推荐此题。基础树型DP。
f[x][i](1 <= i <= p)表示以x为根的子树,变成剩下i个点的子树,且剩余子树包含根结点,需要去掉的最少边数。
那么父结点的f值可以由它所有的儿子的f值做背包得到。
最后的答案是min(min(f[i][p]) + 1 (2 <= i <= n), f[1][p])


/*************************************************************************
Author: WHU_GCC
Created Time: 2007-8-31 12:40:35
File Name: pku1947.cpp
Description: 
***********************************************************************
*/

#include 
<iostream>
#include 
<vector>
using namespace std;
#define out(x) (cout << #x << ": " << x << endl)
const int maxint = 0x7FFFFFFF;
typedef 
long long int64;
const int64 maxint64 = 0x7FFFFFFFFFFFFFFFLL;
template 
<class T> void show(T a, int n) {for (int i = 0; i < n; ++i) cout << a[i] << ' '; cout << endl; }
template 
<class T> void show(T a, int r, int l) {for (int i = 0; i < r; ++i) show(a[i], l); cout << endl; }

const int maxn = 160;
const int inf = 10000;

int n, p;
vector 
<int> v[maxn];
int f[maxn][maxn];

void dfs(int now)
{
    
for (int i = 0; i < v[now].size(); i++)
        dfs(v[now][i]);
    
    f[now][
1= v[now].size();
    
for (int i = 0; i < v[now].size(); i++)
        
for (int k = p - 1; k >= 0; k--if (f[now][k] < inf)
        
{
            
for (int j = 1; j < p; j++if (f[v[now][i]][j] < inf)
                f[now][k 
+ j] <?= f[now][k] + f[v[now][i]][j] - 1;
        }

}


int dp()
{
    
for (int i = 1; i <= n; i++)
        
for (int j = 0; j <= n; j++)
            f[i][j] 
= inf;
    dfs(
1);
    
int ret = inf;
    
for (int i = 2; i <= n; i++)
        ret 
<?= f[i][p] + 1;
    ret 
<?= f[1][p];
    
return ret;
}


int main()
{
    
while (scanf("%d%d"&n, &p) != EOF)
    
{
        
for (int i = 1; i <= n; i++) v[i].clear();
        
for (int i = 0; i < n - 1; i++)
        
{
            
int t1, t2;
            scanf(
"%d%d"&t1, &t2);
            v[t1].push_back(t2);
        }

        printf(
"%d\n", dp());
    }

    
return 0;
}
posted on 2007-08-31 18:27 Felicia 阅读(856) 评论(0)  编辑 收藏 引用 所属分类: 动态规划

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理