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\n", 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("\n");
        }*/
    }
}
/*
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
*/

时间: 2024-10-13 17:32:35

poj1947的相关文章

POJ1947 Rebuilding Roads

Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The cows didn't have time to rebuild any extra roads, so now there is exactly one way to get from any g

POJ-1947 Rebuilding Roads (树形DP+分组背包)

题目大意:将一棵n个节点的有根树,删掉一些边变成恰有m个节点的新树.求最少需要去掉几条边. 题目分析:定义状态dp(root,k)表示在以root为根节点的子树中,删掉一些边变成恰有k个节点的新树需要删去的最少边数.对于根节点root的某个儿子son,要么将son及其所有的子节点全部删掉,则dp(root,k)=dp(root,k)+1,只需删除root与son之间的边:要么在son的子树中选出一些边删掉,构造出有j个节点的子树,状态转移方程为dp(root,k)=max(dp(root,k),

POJ1947 Rebuilding Roads[树形背包]

Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 11495   Accepted: 5276 Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. Th

poj1947(树形dp)

题目链接:http://poj.org/problem?id=1947 题意:给n(n<=150)个点的一棵树,求删掉最少边数k使得最后该树只剩下p(1<=p<=n)个节点.(求最小的k) 分析:设dp[u][j]表示以u节点为根的子树保留j个节点删掉最少的边数:则dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v][k]).初始值dp[u][1]=0. #include <cstdio> #include <cstring> #inclu

March 12th 2015 POJ1947 &lt;9:26&gt;

题目网址:http://poj.org/problem?id=1947: 大意:给定n个点.n-1条边的一棵树,求最少删除多少边使得此时这棵树恰剩有p个结点. 打算今天刚开始做会树形DP,于是就搜到了这道题.也算一道入门题.既然是到DP,显然就可以设状态F[R][i]表示使以R为根节点的子树剩有i个子节点的最小代价.然后考虑它的所有儿子节点s:只有选或者不选: 选的时候:F[R][i]=min(F[s][i-j]+F[R][j])(1<=j<i); 不选的时候:F[R][i]=F[R][i]+

【POJ1947】Rebuilding Roads,树形DP(本文分组背包做法)

题意:给出一颗n个节点的树,要求割去一些边,使得到的树中存在m个节点的树,问最少割断多少条边. 题解: 树形DP无疑!然后就是怎么做了. 首先我们可以想到将节点分配给各子树,做一次dfs,但是做过树形DP的oiers们都知道,因为分配方式近乎于全排列,所以必死,剪枝都剪不活! 好吧,然后就有了左儿子右兄弟的优化,即重新建树,把第一个儿子归为左子节点,然后剩下的儿子都依次往该儿子的右子树上扔,不赘述了,可以自己查,因为本文并不是这种做法(动规神马的太恶心,代码复杂度太大!) 我在这里介绍一下分组背

acm常见算法及例题

转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题 初期:一.基本算法:     (1)枚举. (poj1753,poj2965)     (2)贪心(poj1328,poj2109,poj2586)     (3)递归和分治法.     (4)递推.     (5)构造法.(poj3295)     (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法

【树形dp】Rebuilding Roads

[POJ1947]Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 11934   Accepted: 5519 Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake las

ACM算法总结及刷题参考

参考:http://bbs.byr.cn/#!article/ACM_ICPC/11777 OJ上的一些水题(可用来练手和增加自信)(poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094) 初期: 一.基本算法: (1)枚举. (poj1753,poj2965)    (2)贪心(poj1328,poj2109,poj2586)    (3)递归和分治法.     (4)递推.     (5)构造法.(po