题目链接:http://poj.org/problem?id=1947

Rebuilding Roads
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 13501   Accepted: 6253

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 given barn to any other barn. Thus, the farm transportation system can be represented as a tree.

Farmer John wants to know how much damage another earthquake could do. He wants to know the minimum number of roads whose destruction would isolate a subtree of exactly P (1 <= P <= N) barns from the rest of the barns.

Input

* Line 1: Two integers, N and P

* Lines 2..N: N-1 lines, each with two integers I and J. Node I is node J's parent in the tree of roads.

Output

A single line containing the integer that is the minimum number of roads that need to be destroyed for a subtree of P nodes to be isolated. 

Sample Input

11 6
1 2
1 3
1 4
1 5
2 6
2 7
2 8
4 9
4 10
4 11

Sample Output

2

Hint

[A subtree with nodes (1, 2, 3, 6, 7, 8) will become isolated if roads 1-4 and 1-5 are destroyed.] 
 
题意:给你一颗有n个节点的树,问你最少去掉多少条边可以得到节点数m的子树
思路:一开始没认真看题目,以为题目是问从树上取出m个节点最少要多少条边(取出的节点可以不相连),然后就wa了。。。
看到这题,就很容易想出dp数组,dp[i][j]表示从以i为根节点 的子树中去点j个节点最少要去掉的边数
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct{//链式前向星
int v,next;
}edge[];
int head[];
int dp[][];//dp[i][j]表示在i节点的子树里(不是以i组成的子树)去掉j个节点需要减少的最少的边数
int sum[];//sum[i]表示在i节点的子树里一个有多少个节点(不包括i)
int cnt;
void add(int u,int v){
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
/*
i节点的子树(不包括i)
以i节点为根组成子树(树)(包括i)
*/
int n,m;
void dfs(int k){
sum[k]=;//初始化
for(int i=;i<=n;i++)//初始化
dp[k][i]=1e9;
dp[k][]=;//无论是哪个点,去掉0个节点的花费一定是0
for(int i=head[k];i!=-;i=edge[i].next){
dfs(edge[i].v);//先向子节点搜索
sum[k]+=sum[edge[i].v]+;//计算k节点的子树里有多少个节点
dp[edge[i].v][sum[edge[i].v]+]=;//去除当前子节点为根组成树的所有的节点的花费一定是1(只需断开k与当前子节点的连接)
//printf("%d %d %d\n",edge[i].v,sum[edge[i].v]+1,dp[edge[i].v][sum[edge[i].v]+1]) ;
for(int j=n;j>;j--){ //为什么要j>0,因为j=0的花费一定是0,没必要更新
for(int l=;l<=j;l++)
dp[k][j]=min(dp[k][j],dp[k][j-l]+dp[edge[i].v][l]);
/*为什么l从1开始,因为从0开始没必要(min(dp[k][j],dp[k][j]+dp[edge[i].v][0]);)它的
结果一定是原来的dp[k][j],因为 dp[edge[i].v][0]=0,为什么l可以等于j,因为我可以当前的j个全部
从当前子节点组成的子树去除*/
}
}
}
bool vt[];//标记数组
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
int u,v;
cnt=;
fill(head,head+,false);//初始化
fill(head,head+,-);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
vt[v]=true;
}
int root=;
for(int i=;i<=n&&!root;i++){//找根节点
if(!vt[i])
root=i;
}
dfs(root);
int ans=dp[root][n-m];//我要得到节点数为m的子树,需要去掉n-m个点
for(int i=;i<=n;i++)
if(sum[i]+>=m)
ans=min(ans,dp[i][sum[i]+-m]+);//取以第i个节点为根节点组成的子树(包括i)时,先要减去他与父节点的连接,
//然后再到子树里减去sum[i]+1-m个节点(因为以i为根组成的子树(树)只有sum[i]+1个节点)
printf("%d\n",ans);
} return ;
}

绿色的表示以2节点为根节点组成的子树

红色的表示2节点的子树

poj1947(树形背包)的更多相关文章

  1. poj2486Apple Tree[树形背包!!!]

    Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9989   Accepted: 3324 Descri ...

  2. cdoj 1136 邱老师玩游戏 树形背包

    邱老师玩游戏 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1136 Desc ...

  3. HDU 1011 树形背包(DP) Starship Troopers

    题目链接:  HDU 1011 树形背包(DP) Starship Troopers 题意:  地图中有一些房间, 每个房间有一定的bugs和得到brains的可能性值, 一个人带领m支军队从入口(房 ...

  4. poj 1155 TELE (树形背包dp)

    本文出自   http://blog.csdn.net/shuangde800 题目链接: poj-1155 题意 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构, ...

  5. bzoj 4813: [Cqoi2017]小Q的棋盘 [树形背包dp]

    4813: [Cqoi2017]小Q的棋盘 题意: 某poj弱化版?树形背包 据说还可以贪心... #include <iostream> #include <cstdio> ...

  6. [HAOI2015]树上染色(树形背包)

    有一棵点数为 N 的树,树边有边权.给你一个在 0~ N 之内的正整数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的N-K个点染成白色 . 将所有点染色后,你会获得黑点两两之间的距离加 ...

  7. Luogu 1273 有线电视网 - 树形背包

    Description 树形背包, 遍历到一个节点, 枚举它的每个子节点要选择多少个用户进行转移. Code #include<cstring> #include<cstdio> ...

  8. BZOJ2427: [HAOI2010]软件安装 tarjan+树形背包

    分析: 一开始我以为是裸的树形背包...之后被告知这东西...可能有环...什么!有环! 有环就搞掉就就可以了...tarjan缩点...建图记得建立从i到d[i]之后跑tarjan,因为这样才能判断 ...

  9. [Jsoi2016]最佳团体 BZOJ4753 01分数规划+树形背包/dfs序

    分析: 化简一下我们可以发现,suma*ans=sumb,那么我们考虑二分ans,之后做树形背包上做剪枝. 时间复杂度证明,By GXZlegend O(nklogans) 附上代码: #includ ...

  10. BZOJ 2427 [HAOI2010]软件安装 | 这道树形背包裸题严谨地证明了我的菜

    传送门 BZOJ 2427 题解 Tarjan把环缩成点,然后跑树形背包即可. 我用的树形背包是DFS序上搞的那种. 要注意dp数组初始化成-INF! 要注意dp顺推的时候也不要忘记看数组是否越界! ...

随机推荐

  1. 微信小程序点击列表添加 去除属性

    首先说一下场景:我所循环的数据是对象数组,设置了一个属性当作标记,通过这个标记的值判断是否给改元素添加样式 wxml: <view> <view wx:for="{{lis ...

  2. grep 从文件内容中查找

    grep -rin [查找目标] [查找范围] 例子:在当前目录下的文件内查找test字符串 grep -rin test ./

  3. ACM-ICPC2018南京赛区 Mediocre String Problem

    Mediocre String Problem 题解: 很容易想到将第一个串反过来,然后对于s串的每个位置可以求出t的前缀和它匹配了多少个(EXKMP 或者 二分+hash). 然后剩下的就是要处理以 ...

  4. Mysql 更新时间(加上或者减去一段时间)

    Mysql时间加减函数为date_add().date_sub() 定义和用法 DATE_ADD() 函数向日期添加指定的时间间隔. DATE_SUB() 函数向日期减少指定的时间间隔. 语法 DAT ...

  5. Go语言学习之12 etcd、contex、kafka消费实例、logagent

    本节内容:    1. etcd介绍与使用    2. ElastcSearch介绍与使用 1. etcd介绍与使用    概念:高可用的分布式key-value存储,可以使用配置共享和服务发现    ...

  6. spring boot中利用mybatis-generator插件生成代码

    使用Idea在spring boot中集成mybatis-generator,自动生成mapper.xml  model  dao 文件 一.配置 pom.xml 在pom.xml的<plugi ...

  7. (最完美)红米手机5的Usb调试模式在哪里打开的教程

    就在我们使用安卓手机接通PC的时候,或者使用的有些app比如我们企业营销部门就在使用的app引号精灵,之前老版本就需要开启usb开发者调试模式下使用,现就在新版本不需要了,如果手机没有开启usb开发者 ...

  8. SpringBoot之配置文件加载位置

    1.SpringBoot启动会扫描application.properties或者application.yml文件作为springboot的配置文件.默认创建项目生成application.prop ...

  9. idea 本地tomcat启动控制台乱码问题

    问题:本地tomcat启动,控制台出现中文乱码: 解决办法: 安装了idea发现启动tomcat的时候控制台会有乱码问题,在tomcat配置中添加在VM options填写-Dfile.encodin ...

  10. 模仿WC.exe的功能实现--node.js

    Github项目地址:https://github.com/102derLinmenmin/myWc WC 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要 ...