版权声明:本文为博主原创文章,未经博主允许不得转载。

Rebuilding Roads
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 8227   Accepted: 3672

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.] 

Source

题意:

给你一棵树,求最少剪掉几条边使能够得到一个p个节点的树。

思路:

用dp[i][j]代表以i为根的子树要变成j个节点需要剪掉的边数。

考虑子节点的时候不用考虑它与父节点的那条边,就当不存在,那么最后求的的最小边数加1就行了。
考虑一个节点时,有两种选择,要么剪掉跟子节点相连的边,则dp[i][j] = dp[i][j]+1;

要么不剪掉,则dp[i][j] = max(dp[i][j], dp[i][k]+dp[son][j-k]);

然后随便以一条边dfs求解就行了。

为什么可以这样求解呢。

对于树上的一个节点。要么在待求解子树中。要么不在。在的话即dp[i][p]中。不然的话就肯定在其它子树上了。

详细见代码:

  1. #include <iostream>
  2. #include<stdio.h>
  3. #include<string.h>
  4. using namespace std;
  5. const int maxn=250;
  6. const int INF=0x3f3f3f3f;
  7. struct node
  8. {
  9. int v;
  10. node *next;
  11. } edge[maxn<<1],*head[maxn];
  12. int n,m,cnt,dp[maxn][maxn];
  13. void adde(int u,int v)
  14. {
  15. edge[cnt].v=v;
  16. edge[cnt].next=head[u];
  17. head[u]=&edge[cnt++];
  18. }
  19. void dfs(int fa,int u)
  20. {
  21. int i,j,v,mm=INF;
  22. node *p;
  23. dp[u][1]=0;
  24. for(p=head[u];p!=NULL;p=p->next)
  25. {
  26. v=p->v;
  27. if(v==fa)
  28. continue;
  29. dfs(u,v);
  30. for(i=m;i>=1;i--)//01背包。从大到小装
  31. {
  32. mm=dp[u][i]+1;//不要该子树.
  33. for(j=1;j<i;j++)//要该子树
  34. mm=min(mm,dp[u][j]+dp[v][i-j]);
  35. dp[u][i]=mm;
  36. }
  37. }
  38. }
  39. int main()
  40. {
  41. int i,u,v,ans;
  42. while(~scanf("%d%d",&n,&m))
  43. {
  44. cnt=0;
  45. memset(head,0,sizeof head);
  46. memset(dp,0x3f,sizeof dp);
  47. for(i=1;i<n;i++)
  48. {
  49. scanf("%d%d",&u,&v);
  50. adde(u,v);
  51. adde(v,u);
  52. }
  53. dfs(1,1);
  54. ans=dp[1][m];
  55. for(i=1;i<=n;i++)
  56. ans=min(ans,dp[i][m]+1);//加1是因为根转移了
  57. printf("%d\n",ans);
  58. }
  59. return 0;
  60. }

DP Intro - poj 1947 Rebuilding Roads(树形DP)的更多相关文章

  1. POJ 1947 Rebuilding Roads 树形DP

    Rebuilding Roads   Description The cows have reconstructed Farmer John's farm, with its N barns (1 & ...

  2. POJ 1947 Rebuilding Roads 树形dp 难度:2

    Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9105   Accepted: 4122 ...

  3. DP Intro - poj 1947 Rebuilding Roads

    算法: dp[i][j]表示以i为根的子树要变成有j个节点的状态需要减掉的边数. 考虑状态转移的时候不考虑i的父亲节点,就当不存在.最后统计最少减去边数的 时候+1. 考虑一个节点时,有两种选择,要么 ...

  4. 树形dp(poj 1947 Rebuilding Roads )

    题意: 有n个点组成一棵树,问至少要删除多少条边才能获得一棵有p个结点的子树? 思路: 设dp[i][k]为以i为根,生成节点数为k的子树,所需剪掉的边数. dp[i][1] = total(i.so ...

  5. POJ 1947 Rebuilding Road(树形DP)

    Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, n ...

  6. [poj 1947] Rebuilding Roads 树形DP

    Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 10653 Accepted: 4884 Des ...

  7. POJ 1947 Rebuilding Roads (树dp + 背包思想)

    题目链接:http://poj.org/problem?id=1947 一共有n个节点,要求减去最少的边,行号剩下p个节点.问你去掉的最少边数. dp[u][j]表示u为子树根,且得到j个节点最少减去 ...

  8. POJ1947 - Rebuilding Roads(树形DP)

    题目大意 给定一棵n个结点的树,问最少需要删除多少条边使得某棵子树的结点个数为p 题解 很经典的树形DP~~~直接上方程吧 dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v] ...

  9. POJ 1947 Rebuilding Roads

    树形DP..... Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8188 Accepted: ...

随机推荐

  1. HDU 6153 A Secret (KMP)

    题意:给定两个串,求其中一个串 s 的每个后缀在另一个串 t 中出现的次数. 析:首先先把两个串进行反转,这样后缀就成了前缀.然后求出 s 的失配函数,然后在 t 上跑一遍,如果发现不匹配了或者是已经 ...

  2. RF和GBDT的区别

    Random Forest ​采用bagging思想,即利用bootstrap抽样,得到若干个数据集,每个数据集都训练一颗树. 构建决策树时,每次分类节点时,并不是考虑全部特征,而是从特征候选集中选取 ...

  3. C#记录程序运行时间

    主要:using System.Diagnostics;当中有Stopwatch类: 介绍如下: // 摘要: // 提供一组方法和属性,可用于准确地测量运行时间. public class Stop ...

  4. mybatis 输入、输出映射

    一.输入映射 mapper.xml的参数只有一个.可以传参数,基本简单类型,hashmap和javabean (一).Javabean的方法. 需求:通过小说名和作者模糊找书. 1.定义Javabea ...

  5. Mybatis 多个Mapper

    在实际应用中的,会有较多个mapper.如果每新建一个mapper,就向SqlMapConfig上加上对应的配置文件,会十分不便. 可以新建一个package,在其下面放置Mapper.java,同时 ...

  6. SVN客户端--TortoiseSVN使用说明【转】

    TortoiseSVN是windows下其中一个非常优秀的SVN客户端工具.通过使用它,我们可以可视化的管理我们的版本库.不过由于它只是一个客户端,所以它不能对版本库进行权限管理. TortoiseS ...

  7. thinkjs 框架图

  8. java学习(七)java中抽象类及 接口

    抽象类的特点: A:抽象类和抽象方法必须用abstract关键字修饰. B:抽象类中不一定有抽象方法,但是抽象方法的类必须定义为抽象类 c: 抽象类不能被实例化,因为它不是具体的. 抽象类有构造方法, ...

  9. C#基础入门 三

    C#基础入门 三 类 类使用class关键字进行声明,前面加一个访问修饰符,public class car{} 访问修饰符:修师傅可以用来修饰类和类成员等,控制它们的可见度 修饰符关键字分别为:pu ...

  10. SoapUI设置Cookie

    因為.NET寫的Web Service的方法是需要驗證session的. 需要先call方法Login之後才能使用其它的方法.最近剛在學用SoapUI測試soap的API,剛好可以通過Groovy S ...