poj 1947 Rebuilding Roads 树形dp

来源:互联网 发布:moho动画软件 编辑:程序博客网 时间:2024/05/21 14:04

poj 1947 Rebuilding Roads

http://poj.org/problem?id=1947

题意:给定N个点,之间有路N-1条,且从一点到另一点只有一种走法,问去掉几条路,可分离出由k个点组成的树

 

分组背包思想

 

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn= 205;const int INF= 0x3f3f3f3f;int m, n, value, dp[maxn][maxn], pre[maxn], vis[maxn], son[maxn];struct node{    int v, next;}edge[maxn*2];void add(int aa, int bb){    edge[value].v= bb;    edge[value].next= pre[aa];    pre[aa]= value++;    son[aa]++;}void init(){    int i, j, k, aa, bb;    memset( dp, 0x3f, sizeof( dp));    memset( vis, 0, sizeof( vis));    memset( pre, -1, sizeof( pre));    memset( son, 0, sizeof( son));    value= 1;    for( i=1; i<n; i++){        scanf("%d%d", &aa, &bb);        add(aa, bb);        add(bb, aa);    }    for( i=1; i<=n; i++){        dp[i][1]= son[i];    }}int MIN( int x, int y){    return x<y?x:y;}void dfs(int u){    int i, j, k, p, mm;    for( j= pre[u]; j!= -1; j= edge[j].next){  //枚举所有的组        p= edge[j].v;        if( vis[p]) continue;        vis[p]= 1;        dfs(p);        for( i= m; i>= 0; i--){                  for( k= 0; k<=m; k++){      //枚举组中所有项,注意是0...m,而不是0...son[j]               if( i-k>=0 && dp[u][i-k] < INF && dp[p][k]<INF)  //注意条件               dp[u][i]= MIN(dp[u][i], (dp[u][i-k] + dp[p][k]- 2));            }        }    }}int main(){  //  freopen("1.txt", "r", stdin);    int i, mm;    while( scanf("%d%d", &n, &m) != EOF){        init();        vis[1]= 1;        dfs(1);        for( i=1, mm= INF; i<=n; i++){            if( dp[i][m] < mm) mm= dp[i][m];        }        printf("%d\n", mm);    }    return 0;}