题目链接:

http://codeforces.com/problemset/problem/337/D

题目大意:

给一棵树,m个点,一个距离d,求有多少个点A,使得A到所有的m个点距离都不超过d.

解题思路:

树形dp.

有两种方法可以解:

1、类似于树的直径的求法,先以任意一点作为树根,找到距离该点最远的m中的A点(A点一定是m个点中距离相距最远的两点的一个端点),然后以A点作为树根,依次计算各点到A点的最短距离d1[],并找到距离最远的m中的点B点,然后以B点为树根,依次找到各点到B点的距离d2[].  最后再扫一遍,找到d1和d2都不超过d的点。这种方法求比较简单。

2、先以m中任意一点为树根,在子树中,求出每个节点到达m中的点的最大距离max1,达到max1的直接儿子pre,次大距离。然后再从该根出发,递归维护一个值从父亲过来并且不是通过该节点的最大距离。每次求儿子时判断下,是不是等于该节点的pre,如果是的话,从次大中找。

树很灵活,递归很强大。多做些树上的题。

代码:

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<string>
  6. #include<cstring>
  7. #include<algorithm>
  8. #include<vector>
  9. #include<map>
  10. #include<set>
  11. #include<stack>
  12. #include<list>
  13. #include<queue>
  14. #define eps 1e-6
  15. #define INF 0x1f1f1f1f
  16. #define PI acos(-1.0)
  17. #define ll __int64
  18. #define lson l,m,(rt<<1)
  19. #define rson m+1,r,(rt<<1)|1
  20. #pragma comment(linker, "/STACK:1024000000,1024000000")
  21. using namespace std;
  22.  
  23. //freopen("data.in","r",stdin);
  24. //freopen("data.out","w",stdout);
  25. #define Maxn 110000
  26. //
  27. struct Node
  28. {
  29. int max1,max2,pre; //只用保存在子树中,该点到给定点的最大距离、次大距离以及最大距离的直接儿子编号
  30. //向下推进的时候,维护一个从父亲到达该点的最大值
  31. }node[Maxn];
  32.  
  33. struct Edge
  34. {
  35. int v;
  36. struct Edge *next;
  37. }*head[Maxn<<1],edge[Maxn<<1]; //无向边
  38. bool pm[Maxn];
  39. int n,m,d,ans,cnt;
  40.  
  41. void add(int a,int b)
  42. {
  43. ++cnt;
  44. edge[cnt].v=b;
  45. edge[cnt].next=head[a],head[a]=&edge[cnt];
  46. }
  47. void dfs1(int pre,int cur)
  48. {
  49. if(pm[cur]) //如果是给定的点 距离为0,否则置为无穷大
  50. node[cur].max1=node[cur].max2=0;
  51. else
  52. node[cur].max1=node[cur].max2=-INF;
  53. struct Edge * p=head[cur];
  54. while(p)
  55. {
  56. if(p->v!=pre)
  57. {
  58. dfs1(cur,p->v);//先求出儿子
  59. if(node[p->v].max1+1>=node[cur].max1) //用儿子来更新最大值
  60. {
  61. node[cur].max2=node[cur].max1;//更新次大值
  62. node[cur].max1=node[p->v].max1+1;
  63. node[cur].pre=p->v;
  64. }
  65. else
  66. { //更新次大值
  67. if(node[p->v].max1+1>node[cur].max2)
  68. node[cur].max2=node[p->v].max1+1;
  69. }
  70. }
  71. p=p->next;
  72. }
  73. }
  74. void dfs2(int pre,int cur,int pa) //往下递归的时候,顺便判断,决定出来
  75. {
  76. if(max(node[cur].max1,pa)<=d) //从父亲和孩子的最大距离不超过d的话,肯定是可以的
  77. ans++;
  78. struct Edge * p=head[cur];
  79. while(p)
  80. {
  81. if(p->v!=pre)
  82. {
  83. if(p->v==node[cur].pre) //如果最大值是从该儿子更新过来的,从次大值中选
  84. dfs2(cur,p->v,max(node[cur].max2,pa)+1);
  85. else
  86. dfs2(cur,p->v,max(node[cur].max1,pa)+1);
  87. }
  88. p=p->next;
  89. }
  90. }
  91.  
  92. int main()
  93. {
  94. int a,b,aa;
  95.  
  96. while(~scanf("%d%d%d",&n,&m,&d))
  97. {
  98. memset(pm,false,sizeof(pm));
  99. memset(head,NULL,sizeof(head));
  100. for(int i=1;i<=m;i++)
  101. {
  102. scanf("%d",&a);
  103. pm[a]=true; //标记能够攻击的点
  104. }
  105. for(int i=1;i<n;i++)
  106. {
  107. scanf("%d%d",&aa,&b);
  108. add(aa,b);
  109. add(b,aa);
  110. }
  111. ans=0;
  112. if(pm[1]) //如果是给定的m中点,从父亲过来的为0
  113. {
  114. dfs1(-1,1);
  115. dfs2(-1,1,0);
  116. }
  117. else //如果不是给定的m中的点,从父亲过来的为-INF
  118. {
  119. dfs1(-1,1);
  120. dfs2(-1,1,-INF);
  121. }
  122.  
  123. // dfs1(-1,a);
  124. /* for(int i=1;i<=n;i++)
  125. printf("i:%d %d pre:%d\n",i,node[i].max1,node[i].pre);*/
  126. // dfs2(-1,a,0); //最后一个参数表示从父亲过来的最大距离,
  127. //注意不能从任意一点开始,因为从该点的父亲过来的不为0,为-INF.
  128. printf("%d\n",ans);
  129. }
  130. return 0;
  131. }
  132. /*
  133. 10 1 0
  134. 3
  135. 10 1
  136. 1 3
  137. 8 3
  138. 3 5
  139. 5 7
  140. 5 4
  141. 2 4
  142. 9 4
  143. 6 4
  144. */

树形dp-CF-337D. Book of Evil的更多相关文章

  1. CF 337D Book of Evil 树形DP 好题

    Paladin Manao caught the trail of the ancient Book of Evil in a swampy area. This area contains n se ...

  2. codeforces 337D 树形DP Book of Evil

    原题直通车:codeforces 337D Book of Evil 题意:一棵n个结点的树上可能存在一个Evil,Evil危险范围为d,即当某个点与它的距离x<=d时,那么x是危险的. 现已知 ...

  3. codeforces 337D Book of Evil (树形dp)

    题目链接:http://codeforces.com/problemset/problem/337/D 参考博客:http://www.cnblogs.com/chanme/p/3265913 题目大 ...

  4. CF 219D 树形DP

    CF 219D [题目链接]CF 219D [题目类型]树形DP &题意: 给一个n节点的有向无环图,要找一个这样的点:该点到其它n-1要逆转的道路最少,(边<u,v>,如果v要到 ...

  5. CF EDU 1101D GCD Counting 树形DP + 质因子分解

    CF EDU 1101D GCD Counting 题意 有一颗树,每个节点有一个值,问树上最长链的长度,要求链上的每个节点的GCD值大于1. 思路 由于每个数的质因子很少,题目的数据200000&l ...

  6. CF 486D vailid set 树形DP

    As you know, an undirected connected graph with n nodes and n - 1 edges is called a tree. You are gi ...

  7. CF 461B Appleman and Tree 树形DP

    Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other ...

  8. CF 219D Choosing Capital for Treeland 树形DP 好题

    一个国家,有n座城市,编号为1~n,有n-1条有向边 如果不考虑边的有向性,这n个城市刚好构成一棵树 现在国王要在这n个城市中选择一个作为首都 要求:从首都可以到达这个国家的任何一个城市(边是有向的) ...

  9. CF 463A && 463B 贪心 && 463C 霍夫曼树 && 463D 树形dp && 463E 线段树

    http://codeforces.com/contest/462 A:Appleman and Easy Task 要求是否全部的字符都挨着偶数个'o' #include <cstdio> ...

  10. CF F - Tree with Maximum Cost (树形DP)给出你一颗带点权的树,dist(i, j)的值为节点i到j的距离乘上节点j的权值,让你任意找一个节点v,使得dist(v, i) (1 < i < n)的和最大。输出最大的值。

    题目意思: 给出你一颗带点权的树,dist(i, j)的值为节点i到j的距离乘上节点j的权值,让你任意找一个节点v,使得dist(v, i) (1 < i < n)的和最大.输出最大的值. ...

随机推荐

  1. Java里的IO流里的FileInputStream 的读取并在前打印行数!

    大家好!!新人求罩! import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException ...

  2. [AngularJS] Use ng-model-options to limit $digest

    Refer: http://toddmotto.com/super-fast-angular-ng-model-options-limit-digest-cycles/ Use: <input ...

  3. C#中方法,属性与索引器

    C#中方法,属性与索引器: TODO: 1,关于系统中常常出现的通过某一字段,查询相应实体信息(可能是一条字段或一条数据和一组泛型集合) 解说篇:1,方法,2,属性3.索引器 1.方法(1.依据状态编 ...

  4. PHP安全编程:主机文件目录浏览(转)

    除了能在共享服务器上读取任意文件之外,攻击者还能建立一个可以浏览文件系统的脚本.由于你的大多数敏感文件不会保存在网站主目录下,此类脚本一般用于找到你的源文件的所在位置.请看下例: 01 <?ph ...

  5. windows下如何设置mysql环境变量

    方法一: windows下如何设置mysql环境变量 关键词: mysql, Setting Environment Variables, 环境变量设置 我的电脑->属性->高级-> ...

  6. ASP.NET-FineUI开发实践-11

    我用实例项目写了个子父页面传值,算是比较灵活的写法,可以把js提取出来写成包,然后调用,我先一步一步写,为有困难的朋友打个样. 先画个页面: 上面是个查询用的表单,底下是表格,内存分页,用到了VBox ...

  7. javaScript获取指定的cookie值

    1.获取cookie的函数 function getCookie(cookieName) { var strCookie = document.cookie; var arrCookie = strC ...

  8. 写代码要注意细节,无谓的找前台bug

    <input type="checkbox" name="ckb" value="'+value[0]+'">'真的感觉小细节真 ...

  9. 数据库连接未关闭,conn与rs未关闭

    场景: 2000多人使用系统,早上打卡签到,时间点比较集中. 程序:会创建connction连接.但是未关闭,导致tomcat挂了.导致连接池已满 解决:conn.close,rs.close.记住一 ...

  10. N3292系列资料之RTC介绍

    N3292系列资料之RTC介绍 1 RTC特性 Ø 拥有时间计数器(秒,分,时)和日历计数器,用来计算时间 Ø 绝对定时功能(秒,分,时,日,月,年) Ø 相对定时功能 Ø 支持12小时/24小时模式 ...