poj1947

开学A的第一道题还是1A,感觉还是很开心。

设dp[i][k]为以i为子树的情况下变成一个子树节点为k的最少需要减掉的边数。那么对每个子树背包就可以了,注意的是刚开始需要将dp[a][1] = a != 1?num[a]-1:num[a];的意思是把a的与孩子连的边全部去掉时的情况,然后一步一步背包加边。

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int maxa = 155;
int edge[maxa][maxa];
int num[maxa];
int dp[maxa][maxa];     //包括i且只考虑i的子树的所有最小情况,
int nt[maxa];           //以i为根的字数的节点数
int ans;
    int n, p;
    int dp1[maxa];
int dfs(int a, int fa){
    nt[a] = 1;
    for(int i = 0; i < num[a]; i++){
        int k = edge[a][i];
        if(k != fa){
            dfs(k, a);
        }
    }
    dp[a][1] = a != 1?num[a]-1:num[a];

    for(int i = 0; i < num[a]; i++){
        int k = edge[a][i];
        if(k != fa){
            for(int j = 1; j <= nt[a] + nt[k]; j ++){
                dp1[j] = dp[a][j];
            }
            for(int j = 1; j <= nt[a]; j++){
                for(int h = 1; h <= nt[k]; h++){
                    dp1[j+h] = min(dp1[j+h], dp[a][j] + dp[k][h]-1);
                }
            }
            for(int j = 1; j <= nt[a] + nt[k]; j ++){
                dp[a][j] = dp1[j];
            }
            nt[a] += nt[k];
        }
    }
    if(a == 1){
        ans = min(ans, dp[a][p]);
    }else ans = min(ans, dp[a][p] + 1);
}
int main(){
    while(scanf("%d%d", &n, &p)!=EOF){
        int a, b;
        memset(num, 0, sizeof(num));
        for(int i  = 1; i < n; i++){
            scanf("%d%d", &a, &b);
            edge[a][num[a]++] = b;
            edge[b][num[b]++] = a;
        }
        for(int i = 1; i <= n; i++){
            for(int k =  1; k <= n; k++){
                dp[i][k] = maxa;
            }
        }
        ans = maxa;
        dfs(1, 0);
        printf("%d
", ans);/*
        for(int  i = 1; i <= n; i++){
            printf("%d %d * ", nt[i], i);
            for(int k = 1; k <= n; k++){
                printf("%d ", dp[i][k]);
            }printf("
");
        }*/
    }
}
/*
11 6
1 2
1 3
1 4
1 5
2 6
2 7
2 8
4 9
4 10
4 11
11 1
1 2
1 3
1 4
1 5
2 6
2 7
2 8
4 9
4 10
4 11
*/
View Code
原文地址:https://www.cnblogs.com/icodefive/p/4309308.html