题目链接: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. 编译原理中DFA最小化

    关于编译原理最小化的操作,专业术语请移步至:http://www.360doc.com/content/18/0601/21/11962419_758841916.shtml 这里只是记录一下个人的理 ...

  2. Cocos Creator学习五:触摸和重力传感响应事件

    1.移动设备上主要涉及触摸响应事件以及重力传感响应事件的处理. 事件主要分两类: 针对节点事件处理的节点响应事件cc.Node.EventType(主要是触摸响应事件和鼠标响应事件): 针对全局系统事 ...

  3. js对象跟数组多层嵌套,检测没有此数据就添加有则不添加以及超过限制条件删除操作

    例如你需要这样格式的数据: [{"name":"合肥市","arrey":[{"lat":"31.862323 ...

  4. [Web Service] Java Web Services Tutorial

    两种主要的java web services api: JAX-WS 和JAX-RS. Java web service application 之间通过WSDL来交互. 有两种方法来书写java w ...

  5. mysql 表关联批量更新

    项目中最近遇到了需要手动修改某个表的某个字段的数据,但是这个数据是来自别的表,需要关联,所以需要用到关联的批量更新,特此记录一下. UPDATE t_account_trans_info AS iiI ...

  6. 【Java】【10】后台处理Emoji表情

    问题:存到数据库的emoji表情,取出来后,在前端显示为乱码 环境:SpringBoot + Oracle(MySQL据说是支持表情的) 解决方案: 引入emoji相关的jar包,使用很方便,不过表情 ...

  7. React文档(十八)最佳性能

    在内部,React使用好几种聪明的技巧去最小化更新UI所需要的DOM操作.对于很多应用来说,使用React会使得构建用户界面非常之快而且不需要做太多专门的性能优化.虽然如此,还是有一些方法可以让你为R ...

  8. angular 引入编辑器以及控制器的学习和理解。。。

    在angular中引入编辑器的时候花了很长时间,然后发现自己以前根本就没好好用过angular,因为项目是接手的学姐的,学姐又是接手的学姐的,到我这里就只是写写页面的事了. 引入编辑器差了好多好多资料 ...

  9. highchart 十字准星 crosshairs

    crosshairs: true, crosshairs: [true, true], // 同时启用竖直及水平准星线 crosshairs: [{ // 设置准星线样式 width: 2, colo ...

  10. 这里我们介绍的是 40+ 个非常有用的 Oracle 查询语句,主要涵盖了日期操作,获取服务器信息,获取执行状态,计算数据库大小等等方面的查询。这些是所有 Oracle 开发者都必备的技能,所以快快收藏吧!

    日期/时间 相关查询 获取当前月份的第一天 运行这个命令能快速返回当前月份的第一天.你可以用任何的日期值替换 “SYSDATE”来指定查询的日期. SELECT TRUNC (SYSDATE, 'MO ...