题意:

给你一棵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]就可以了

/*
这就是一个树形dp(也就是依据树的边进行dp)
*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define mem(a) memset(a,0,sizeof(a))
#define mem__(a) memset(a,-1,sizeof(a))
typedef long long ll;
const int maxn=200010;
const int INF=0x3f3f3f3f;
const double blo=(1.0+sqrt(5.0))/2.0;
const double eps=1e-8;
/*
child[x]表示以1为根节点情况下,以x为根的子树上能到达x节点上的最大流
然后你知道dp[x]和child[to]之后就可以求出来dp[to]
因为dp[x]减去从to这个子树上来的流量就是其他节点到x的流量,那么就可以知道其他节点到to节点的流量
dp[to]=child[to]+min(dp[x]-min(e[i].dis,child[to]),e[i].dis); */
int n,head[maxn],child[maxn],du[maxn],dp[maxn],num;
struct Edge{
int next,to,dis;
}e[2*maxn];
void add_edge(int from,int to,int dis){
e[++num].next=head[from];
e[num].to=to;
e[num].dis=dis;
head[from]=num;
}
int dfs_child(int x,int fa)
{
int sum=0;
for(int i=head[x];i!=-1;i=e[i].next)
{
int to=e[i].to;
if(to==fa) continue;
sum+=min(dfs_child(to,x),e[i].dis);
}
child[x]=sum;
if(du[x]==1) return e[head[x]].dis;
else return child[x];
}
void dfs(int x,int fa)
{
for(int i=head[x];i!=-1;i=e[i].next)
{
int to=e[i].to;
if(to==fa) continue;
/*
要加这个特判,因为如果我们的1点是一个叶节点(就是我们挑选了一个叶节点为根开始遍历),那么这个叶节点的子节点
的dp值就需要是加上child[to],然后再加上父节点的边权,你画个图理解一下
如果不加这个判断会卡下面这个数据,你按照这个数据画个图
1
3
1 2 1
2 3 1
*/
if(du[x]==1) dp[to]=child[to]+e[i].dis;
else
dp[to]=child[to]+min(dp[x]-min(e[i].dis,child[to]),e[i].dis);
dfs(to,x);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
num=0;
mem(child);
mem(dp);
mem(du);
mem__(head);
for(int i=1;i<n;++i)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
du[x]++;
du[y]++;
add_edge(x,y,z);
add_edge(y,x,z);
}
dp[1]=dfs_child(1,-1);
dfs(1,-1);
int maxx=0;
for(int i=1;i<=n;++i)
maxx=max(maxx,dp[i]);
printf("%d\n",maxx);
}
return 0;
}

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. MySQL常用的数据类型和字段属性

    数据类型 数值 tinyint 十分小的数据 1个字节 smallint 较小的数据 2个字节 mediumint 中等大小的数据 3个字节 int 标准的整数 4个字节 常用 bigint 较大的数 ...

  2. 【栈和队列】5、队列概述与数组队列的基本实现 - Java

    3-5 数组队列 简单记录 - bobo老师的玩转算法系列–玩转数据结构 - 栈和队列 队列Queue 队列也是一种线性结构 相比数组,队列对应的操作是数组的子集 只能从一端(队尾)添加元素,只能从另 ...

  3. 【Spring】XML方式实现(无参构造 有参构造)和注解方式实现 IoC

    文章目录 Spring IoC的实现方式 XML方式实现 通过无参构造方法来创建 1.编写一个User实体类 2.编写我们的spring文件 3.测试类 UserTest.java 4.测试结果 通过 ...

  4. AgileConfig - RESTful API 介绍

    AgileConfig AgileConfig是一个基于.net core开发的轻量级配置中心. AgileConfig秉承轻量化的特点,部署简单.配置简单.使用简单.学习简单,它只提取了必要的一些功 ...

  5. SDUST数据结构 - chap4 串

    函数题: 6-1 查找子串: 裁判测试程序样例: #include <stdio.h> #define MAXS 30 char *search(char *s, char *t); vo ...

  6. 错误捕捉过滤器 .NetCore版

    前言 继承ExceptionFilterAttribute后,重写OnException函数. 统一捕捉所有报错,格式化返回前端. 代码实现 基类控制器 在基类控制器上添加[ErrorCatch]特性 ...

  7. 转 jmeter测试手机号码归属地

    jmeter测试手机号码归属地   jmeter测试手机号码归属地接口时,HTTP请求有以下两种书写方法: 1.请求和参数一同写在路径中 2.参数单独写在参数列表中 请求方法既可以使用GET方法又可以 ...

  8. 解决JavaScript中构造函数浪费内存的问题!

    解决JavaScript中构造函数浪费内存的问题! 把构造函数中的公共的方法放到构造函数的原型对象上! // 构造函数的问题! function Gouzaohanshu(name, age, gen ...

  9. GStreamer各个包构建

    GStreamer按功能.维护的标准化程度.依赖库的版权差异等分了若干个包(package),如 gstreamer, gst-plugins-base, gst-plugins-good, gst- ...

  10. 解决Spirng注入时名称下的红色波浪线

    解决Spirng注入时名称下的红色波浪线 报错情形: 解决办法: 方案一: 如果可以正常运行,那么可能是类没有交给Spring管理,如下图,我们只需要在对应的接口(或者类上)加上@Component注 ...