题目链接:https://vjudge.net/problem/HYSBZ-1509

我参考的证明的论文:8.陈瑜希《多角度思考 创造性思维》_百度文库  https://wenku.baidu.com/view/f3b19d0b79563c1ec5da710e.html

我参考的博客:BZOJ1509: [NOI2003]逃学的小孩 - Cynthia_wjyi - CSDN博客  https://blog.csdn.net/cynthia_wjyi/article/details/50381405

第一道树形DP的题目,这里主要是寻找每一个点到其他点的距离里面最大的三个值,做两次记忆化搜索(DFS),第一次搜索求以每个点为根节点的子树(假设点1是整棵树的根节点)到它的所有儿子节点的距离里面最大的三个值(用数组mx1,mx2,mx3储存),第二次搜索是计算以每个点为子树,然后这个根节点到子树之外的所有点的距离里面的最大值(用数组f储存)。假设以点a为分叉点,那么点a的父亲到点a只有一条路,所以只要用f数组存一个子树外的最大值,剩下的两个就是子树里面的最大的两个距离,结果就是a+2*b+c,看不懂的话就看上面推荐的论文吧,我比较菜。

代码:(我可是加了注释的良心人)

  1. #include<iostream>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<queue>
  5. #include<map>
  6. #include<stack>
  7. #include<cmath>
  8. #include<vector>
  9. #include<set>
  10. #include<cstdio>
  11. #include<string>
  12. #include<deque>
  13. using namespace std;
  14. typedef long long LL;
  15. #define eps 1e-8
  16. #define INF 0x3f3f3f3f
  17. #define maxn 200005
  18. /*struct point{
  19. int u,w;
  20. };
  21. bool operator <(const point &s1,const point &s2)
  22. {
  23. if(s1.w!=s2.w)
  24. return s1.w>s2.w;
  25. else
  26. return s1.u>s2.u;
  27. }*/
  28. struct node{
  29. int v,next;
  30. LL w;
  31. }edge[maxn<<];
  32. int head[maxn];
  33. int n,m,k,t,cnt;
  34. LL mx1[maxn],mx2[maxn],mx3[maxn],f[maxn],ans;//mx1[i]代表点i为根到所有儿子距离的最大值
  35. //f[i]表示点i到点i为根的子树外的所有点的距离最大值
  36. bool vis[maxn];
  37. void DFS(int u){//求出以u为根的子树中,点u到它的儿子节点的所有距离里面的最大三个
  38. vis[u]=true;
  39. for(int i=head[u];i!=-;i=edge[i].next){
  40. int v=edge[i].v;
  41. LL w=edge[i].w;
  42. if(!vis[v]){
  43. DFS(v);
  44. mx3[u]=max(mx3[u],mx1[v]+w);//这里为什么这么写需要自己推敲一下
  45. if(mx3[u]>mx2[u]) swap(mx2[u],mx3[u]);
  46. if(mx2[u]>mx1[u]) swap(mx1[u],mx2[u]);
  47. }
  48. }
  49. }
  50. void DFS1(int u){//往父节点方向找子树之外的点到点u的最大距离
  51. vis[u]=true;
  52. for(int i=head[u];i!=-;i=edge[i].next){
  53. int v=edge[i].v;
  54. LL w=edge[i].w;
  55. if(!vis[v]){
  56. f[v]=f[u]+w;
  57. if(mx1[u]==mx1[v]+w)//离点u距离最大的儿子节点在以点v为根节点的子树里面
  58. f[v]=max(f[v],mx2[u]+w);
  59. else
  60. f[v]=max(f[v],mx1[u]+w);
  61. DFS1(v);
  62. }
  63. }
  64. }
  65. void cal(LL a,LL b,LL c){
  66. if(a<b) swap(a,b);//排序
  67. if(a<c) swap(a,c);
  68. if(b<c) swap(b,c);
  69. ans=max(ans,a+*b+c);
  70. }
  71. void init(){
  72. memset(head,-,sizeof(head));
  73. memset(mx1,,sizeof(mx1));
  74. memset(mx2,,sizeof(mx2));
  75. memset(mx3,,sizeof(mx3));
  76. memset(f,,sizeof(f));
  77. cnt=ans=;
  78. }
  79. void add(int u,int v,LL w){
  80. edge[++cnt].v=v;
  81. edge[cnt].w=w;
  82. edge[cnt].next=head[u];
  83. head[u]=cnt;
  84. }
  85. int main()
  86. {
  87. scanf("%d%d",&n,&m);
  88. init();
  89. int u,v;
  90. LL w;
  91. for(int i=;i<=m;i++){
  92. scanf("%d%d%lld",&u,&v,&w);
  93. add(u,v,w);
  94. add(v,u,w);
  95. }
  96. memset(vis,false,sizeof(vis));
  97. DFS();
  98. memset(vis,false,sizeof(vis));
  99. DFS1();
  100. for(int i=;i<=n;i++){//以每个点为分叉点的情况都算一遍
  101. if(f[i]>mx3[i])
  102. cal(mx1[i],mx2[i],f[i]);
  103. else
  104. cal(mx1[i],mx2[i],mx3[i]);
  105. }
  106. printf("%lld\n",ans);
  107. return ;
  108. }

树形DP(记忆化搜索) HYSBZ - 1509的更多相关文章

  1. 【bzoj5123】[Lydsy12月赛]线段树的匹配 树形dp+记忆化搜索

    题目描述 求一棵 $[1,n]$ 的线段树的最大匹配数目与方案数. $n\le 10^{18}$ 题解 树形dp+记忆化搜索 设 $f[l][r]$ 表示根节点为 $[l,r]$ 的线段树,匹配选择根 ...

  2. [题解](树形dp/记忆化搜索)luogu_P1040_加分二叉树

    树形dp/记忆化搜索 首先可以看出树形dp,因为第一个问题并不需要知道子树的样子, 然而第二个输出前序遍历,必须知道每个子树的根节点,需要在树形dp过程中记录,递归输出 那么如何求最大加分树——根据中 ...

  3. 刷题总结——二叉苹果树(ssoj树形dp+记忆化搜索)

    题目: 题目背景 URAL:http://acm.timus.ru/problem.aspx?space=1&num=1018 题目描述 有一棵苹果树,如果树枝有分叉,一定是分 2 叉(就是说 ...

  4. 刷题总结——选课(ssoj树形dp+记忆化搜索+多叉树转二叉树)

    题目: 题目描述 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了 N(N<300)门的选修课程,每个学生可选课程的数量 M 是给定的.学生选修了这M门课 ...

  5. 加分二叉树 vijos1991 NOIP2003第三题 区间DP/树形DP/记忆化搜索

    描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,-,n),其中数字1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都有一 ...

  6. 【BZOJ】1415 [Noi2005]聪聪和可可 期望DP+记忆化搜索

    [题意]给定无向图,聪聪和可可各自位于一点,可可每单位时间随机向周围走一步或停留,聪聪每单位时间追两步(先走),问追到可可的期望时间.n<=1000. [算法]期望DP+记忆化搜索 [题解]首先 ...

  7. poj1664 dp记忆化搜索

    http://poj.org/problem?id=1664 Description 把M个相同的苹果放在N个相同的盘子里,同意有的盘子空着不放,问共同拥有多少种不同的分法?(用K表示)5.1.1和1 ...

  8. 状压DP+记忆化搜索 UVA 1252 Twenty Questions

    题目传送门 /* 题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来 状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1.答案对错集合为s2时,还要问几次才能区分出来 若 ...

  9. ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. Poor Ramzi -dp+记忆化搜索

    ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. ...

  10. POJ 1088 DP=记忆化搜索

    话说DP=记忆化搜索这句话真不是虚的. 面对这道题目,题意很简单,但是DP的时候,方向分为四个,这个时候用递推就好难写了,你很难得到当前状态的前一个真实状态,这个时候记忆化搜索就派上用场啦! 通过对四 ...

随机推荐

  1. Linux 创建用户并赋予 Sudo 权限

    01,创建账号 => useradd admin 02,赋予密码 => passwd admin 03,修改 sudo 权限文件,使得该用户可以使用 sudo 命令 vim /etc/su ...

  2. 03.设计模式_抽象工厂模式(Abstract Fcatory)

    抽象工厂模式:创建一些列相关或者互相依赖的对象的接口,而无需指定他们具体的类, 1.创建工厂Factory: package patterns.design.factory; import java. ...

  3. delphi 属性 参数 新注释

    delphi 属性 参数 新注释,在写代码的时候,可以自动看到属性.参数的的备注说明,太方便了. Tmyclass=class /// <summary> /// 姓名 /// </ ...

  4. 2 算法查找&排序问题

    一.查找 1.查找的概念: 2 顺序查找(linear search) 从头找到尾 def linear_search(li,val): for ind ,v in enumerate(li): if ...

  5. django 之manytomany

    https://www.cnblogs.com/changbaishan/p/8056762.html https://blog.csdn.net/hpu_yly_bj/article/details ...

  6. Kotlin语言学习笔记(3)

    数据类(Data Classes) data class User(val name: String, val age: Int) 编译器自动生成的有: equals()/hashCode() toS ...

  7. LeetCode OJ 94. Binary Tree Inorder Traversal

    Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary tre ...

  8. 自行编译mwan加入openwrt里

    参考源文:http://www.right.com.cn/forum/thread-124449-1-1.html 本例以 opoenwrt 12.09正式版为例,原软件来自openwrt 英文论坛: ...

  9. cap文件的格式说明

    前面24个字节是.cap文件的文件头. 头信息对应的结构体为:struct pcap_file_header {  bpf_u_int32 magic;  u_short version_major; ...

  10. ckeditor使用说明

      2015-08-17 15:42热心网友最快回答 一.使用方法:1.在页面<head>中引入ckeditor核心文件ckeditor.js<script type="t ...