题意:

给你一棵n个顶点的树,有n-1条边,每一条边有一个容量z,表示x点到y点最多能通过z容量的水。

你可以任意选择一个点,然后从这个点倒水,然后水会经过一些边流到叶节点从而流出。问你最多你能倒多少容量的水

示例:

A(1)= 11 + 5 + 8 = 24
详情:1-> 2 11
1-> 4-> 3 5
1-> 4-> 5 8(因为1-> 4的容量为13)
A(2)= 5 + 6 = 11
详细信息:2-> 1-> 4-> 3 5
2-> 1-> 4-> 5 6
A(3)= 5
详细信息:3-> 4-> 5 5
A(4)= 11 + 5 + 10 = 26
详细信息:4-> 1-> 2 11
4-> 3 5
4-> 5 10
A(5)= 10
详细信息:5-> 4-> 1-> 2 10

因为A(4)最大,所以最多能倒26容量的水

题解:

我们可以先随便找一个点当作树根,我这里选择节点1

然后我们可以dfs一遍去获取每一个节点能从它的子节点中的叶节点流出水的量,用数组d来保存

求出来所有节点的d值之后,这个时候1节点的流量就是d[1],也就是A(1)=d[1]

这个时候我们求A(2)

我们可以先将A(1)减去2节点来的流量

ans=dp[1]-min(1->2,d[2])

然后这个ans和1->2这一条边取最小值,就是不属于2的子节点的其他叶节点能到2节点的流量

这个时候再加上d[2]就可以了

  1. /*
  2. 这就是一个树形dp(也就是依据树的边进行dp)
  3. */
  4. #include<stdio.h>
  5. #include<string.h>
  6. #include<math.h>
  7. #include<algorithm>
  8. #include<iostream>
  9. using namespace std;
  10. #define mem(a) memset(a,0,sizeof(a))
  11. #define mem__(a) memset(a,-1,sizeof(a))
  12. typedef long long ll;
  13. const int maxn=200010;
  14. const int INF=0x3f3f3f3f;
  15. const double blo=(1.0+sqrt(5.0))/2.0;
  16. const double eps=1e-8;
  17. /*
  18. child[x]表示以1为根节点情况下,以x为根的子树上能到达x节点上的最大流
  19. 然后你知道dp[x]和child[to]之后就可以求出来dp[to]
  20. 因为dp[x]减去从to这个子树上来的流量就是其他节点到x的流量,那么就可以知道其他节点到to节点的流量
  21. dp[to]=child[to]+min(dp[x]-min(e[i].dis,child[to]),e[i].dis);
  22.  
  23. */
  24. int n,head[maxn],child[maxn],du[maxn],dp[maxn],num;
  25. struct Edge{
  26. int next,to,dis;
  27. }e[2*maxn];
  28. void add_edge(int from,int to,int dis){
  29. e[++num].next=head[from];
  30. e[num].to=to;
  31. e[num].dis=dis;
  32. head[from]=num;
  33. }
  34. int dfs_child(int x,int fa)
  35. {
  36. int sum=0;
  37. for(int i=head[x];i!=-1;i=e[i].next)
  38. {
  39. int to=e[i].to;
  40. if(to==fa) continue;
  41. sum+=min(dfs_child(to,x),e[i].dis);
  42. }
  43. child[x]=sum;
  44. if(du[x]==1) return e[head[x]].dis;
  45. else return child[x];
  46. }
  47. void dfs(int x,int fa)
  48. {
  49. for(int i=head[x];i!=-1;i=e[i].next)
  50. {
  51. int to=e[i].to;
  52. if(to==fa) continue;
  53. /*
  54. 要加这个特判,因为如果我们的1点是一个叶节点(就是我们挑选了一个叶节点为根开始遍历),那么这个叶节点的子节点
  55. 的dp值就需要是加上child[to],然后再加上父节点的边权,你画个图理解一下
  56. 如果不加这个判断会卡下面这个数据,你按照这个数据画个图
  57. 1
  58. 3
  59. 1 2 1
  60. 2 3 1
  61. */
  62. if(du[x]==1) dp[to]=child[to]+e[i].dis;
  63. else
  64. dp[to]=child[to]+min(dp[x]-min(e[i].dis,child[to]),e[i].dis);
  65. dfs(to,x);
  66. }
  67. }
  68. int main()
  69. {
  70. int t;
  71. scanf("%d",&t);
  72. while(t--)
  73. {
  74. scanf("%d",&n);
  75. num=0;
  76. mem(child);
  77. mem(dp);
  78. mem(du);
  79. mem__(head);
  80. for(int i=1;i<n;++i)
  81. {
  82. int x,y,z;
  83. scanf("%d%d%d",&x,&y,&z);
  84. du[x]++;
  85. du[y]++;
  86. add_edge(x,y,z);
  87. add_edge(y,x,z);
  88. }
  89. dp[1]=dfs_child(1,-1);
  90. dfs(1,-1);
  91. int maxx=0;
  92. for(int i=1;i<=n;++i)
  93. maxx=max(maxx,dp[i]);
  94. printf("%d\n",maxx);
  95. }
  96. return 0;
  97. }

poj3585 Accumulation Degree(树形dp,换根)的更多相关文章

  1. poj3585 Accumulation Degree[树形DP换根]

    思路其实非常简单,借用一下最大流求法即可...默认以1为根时,$f[x]$表示以$x$为根的子树最大流.转移的话分两种情况,一种由叶子转移,一种由正常孩子转移,判断一下即可.换根的时候由頂向下递推转移 ...

  2. $Poj3585\ Accumulation Degree$ 树形$DP/$二次扫描与换根法

    Poj Description 有一个树形的水系,由n-1条河道与n个交叉点组成.每条河道有一个容量,联结x与y的河道容量记为c(x,y),河道的单位时间水量不能超过它的容量.有一个结点是整个水系的发 ...

  3. bzoj 3743 [Coci2015]Kamp——树形dp+换根

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 树形dp+换根. “从根出发又回到根” 减去 “mx ” . 注意dfsx里真的要改那 ...

  4. 树形dp换根,求切断任意边形成的两个子树的直径——hdu6686

    换根dp就是先任取一点为根,预处理出一些信息,然后在第二次dfs过程中进行状态的转移处理 本题难点在于任意割断一条边,求出剩下两棵子树的直径: 设割断的边为(u,v),设down[v]为以v为根的子树 ...

  5. [题解](树形dp/换根)小x游世界树

    2. 小x游世界树 (yggdrasi.pas/c/cpp) [问题描述] 小x得到了一个(不可靠的)小道消息,传说中的神岛阿瓦隆在格陵兰海的某处,据说那里埋藏着亚瑟王的宝藏,这引起了小x的好奇,但当 ...

  6. POJ3585:Accumulation Degree(换根树形dp)

    Accumulation Degree Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3425   Accepted: 85 ...

  7. 题解 poj3585 Accumulation Degree (树形dp)(二次扫描和换根法)

    写一篇题解,以纪念调了一个小时的经历(就是因为边的数组没有乘2 phhhh QAQ) 题目 题目大意:找一个点使得从这个点出发作为源点,流出的流量最大,输出这个最大的流量. 以这道题来介绍二次扫描和换 ...

  8. POJ3585 Accumulation Degree (树形DP-二次扫描与换根)

    本题属于不定根的树形DP,若以每个节点为根求解一次,复杂度太高,所以可以用换根的技巧. d[u]表示以u为根向下可以流的最大流量,这个是比较好求的,直接遍历到叶子节点,由子节点信息更新父节点.然后进行 ...

  9. POJ3585 Accumulation Degree【换根dp】

    题目传送门 题意 给出一棵树,树上的边都有容量,在树上任意选一个点作为根,使得往外流(到叶节点,叶节点可以接受无限多的流量)的流量最大. 分析 首先,还是从1号点工具人开始$dfs$,可以求出$dp[ ...

随机推荐

  1. 【SpringBoot1.x】SpringBoot1.x 缓存

    SpringBoot1.x 缓存 文章源码 JSR107 Java Caching 定义了 5 个核心接口,分别为: CachingProvider 定义了创建.配置.获取.管理和控制多个 Cache ...

  2. 【C++】《C++ Primer 》第十章

    第十章 泛型算法 一.概述 因为它们实现共同的操作,所以称之为"算法".而"泛型",指的是它们可以操作在多种容器类型上. 泛型算法并不直接操作容器,而是遍历由两 ...

  3. Flutter 布局类组件:简介

    前言 布局类组件都会包含一个或多个子组件,不同的布局类组件对子组件排版(layout)方式不同. 我们知道,Element树才是最终的绘制树,Element树是通过Widget树来创建的(通过Widg ...

  4. Educational Codeforces Round 102 (Rated for Div. 2)

    比赛地址 A(水题) 题目链接 题目: 给出一个数组\(a\)并能进行一个操作使得数组元素更改为数组任意其他两元素之和,问是否可以让数组元素全部小于等于\(d\) 解析: 排序后判断最大值是否小于等于 ...

  5. Writing in the science: Introducion

    1.what makes a good writing? 2.what makes a good writer? 1) have something to say 2) logical thinkin ...

  6. Hbase Region合并

    业务场景: Kafka+SparkStreaming+Hbase由于数据大量的迁移,再加上业务的改动,新增了很多表,导致rerigon总数接近4万(36个节点) 组件版本: Kafka:2.1.1 S ...

  7. oracle 12C单实例打PSU

    前提: oracle不管打什么样的补丁,readme都是很好的参考资料. Oracle每季度都会更新一个最新的PSU,现在12.1.0.2.0的最新的PSU是Patch 26925311. 由于今天白 ...

  8. SAP系统跨平台字符编码转换

    SAP系统在进行了夸平台的迁移,可能会遇到操作系统层文件编码不同,导致SAP系统无法识别或者乱码的问题.例如SAP系统从AIX平台迁移到linux平台,SAP应用服务器的编码会发生变化,从4102变化 ...

  9. MongoDB查询优化--explain,慢日志

    引入 与Mysql数据库一样,MongoDB也有自己的查询优化工具,explain和慢日志 explain shell命令格式 db.collection.explain().<method(. ...

  10. 核酸检测:让我明白AQS原理

    春节越来越近了,疫情也越来越严重,但挡不住叫练携一家老小回老家(湖北)团聚的冲动.响应国家要求去我们做核酸检测了. 独占锁 早上叫练带着一家三口来到了南京市第一医院做核酸检测,护士小姐姐站在医院门口拦 ...