poj3585 Accumulation Degree(树形dp,换根)
题意:
给你一棵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,换根)的更多相关文章
- poj3585 Accumulation Degree[树形DP换根]
思路其实非常简单,借用一下最大流求法即可...默认以1为根时,$f[x]$表示以$x$为根的子树最大流.转移的话分两种情况,一种由叶子转移,一种由正常孩子转移,判断一下即可.换根的时候由頂向下递推转移 ...
- $Poj3585\ Accumulation Degree$ 树形$DP/$二次扫描与换根法
Poj Description 有一个树形的水系,由n-1条河道与n个交叉点组成.每条河道有一个容量,联结x与y的河道容量记为c(x,y),河道的单位时间水量不能超过它的容量.有一个结点是整个水系的发 ...
- bzoj 3743 [Coci2015]Kamp——树形dp+换根
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 树形dp+换根. “从根出发又回到根” 减去 “mx ” . 注意dfsx里真的要改那 ...
- 树形dp换根,求切断任意边形成的两个子树的直径——hdu6686
换根dp就是先任取一点为根,预处理出一些信息,然后在第二次dfs过程中进行状态的转移处理 本题难点在于任意割断一条边,求出剩下两棵子树的直径: 设割断的边为(u,v),设down[v]为以v为根的子树 ...
- [题解](树形dp/换根)小x游世界树
2. 小x游世界树 (yggdrasi.pas/c/cpp) [问题描述] 小x得到了一个(不可靠的)小道消息,传说中的神岛阿瓦隆在格陵兰海的某处,据说那里埋藏着亚瑟王的宝藏,这引起了小x的好奇,但当 ...
- POJ3585:Accumulation Degree(换根树形dp)
Accumulation Degree Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3425 Accepted: 85 ...
- 题解 poj3585 Accumulation Degree (树形dp)(二次扫描和换根法)
写一篇题解,以纪念调了一个小时的经历(就是因为边的数组没有乘2 phhhh QAQ) 题目 题目大意:找一个点使得从这个点出发作为源点,流出的流量最大,输出这个最大的流量. 以这道题来介绍二次扫描和换 ...
- POJ3585 Accumulation Degree (树形DP-二次扫描与换根)
本题属于不定根的树形DP,若以每个节点为根求解一次,复杂度太高,所以可以用换根的技巧. d[u]表示以u为根向下可以流的最大流量,这个是比较好求的,直接遍历到叶子节点,由子节点信息更新父节点.然后进行 ...
- POJ3585 Accumulation Degree【换根dp】
题目传送门 题意 给出一棵树,树上的边都有容量,在树上任意选一个点作为根,使得往外流(到叶节点,叶节点可以接受无限多的流量)的流量最大. 分析 首先,还是从1号点工具人开始$dfs$,可以求出$dp[ ...
随机推荐
- 【Redis3.0.x】数据类型
Redis3.0.x 数据类型 五大数据类型 String(字符串) string 是 redis 最基本的类型.可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value. ...
- 剑指offer 面试题9.1:用两个队列实现栈
题目描述 使用队列实现栈的下列操作:push(x) -- 元素 x 入栈:pop() -- 移除栈顶元素:top() -- 获取栈顶元素:empty() -- 返回栈是否为空: 编程思想 利用双队列实 ...
- Linux面试必备
1.Linux的体系结构
- iptables自动屏蔽访问网站最频繁的IP
iptables自动屏蔽访问网站频繁的IP 屏蔽每分钟访问超过200的IP 方法1:根据访问日志(Nginx为例 #!/bin/bash DATE=$(date +%d/%b/%Y:%H:%M) AB ...
- 利用sklearn进行字典&文本的特征提取
写在前面 这篇博客主要内容: 应用DictVectorizer实现对类别特征进行数值化.离散化 应用CountVectorizer实现对文本特征进行数值化 特征提取API sklearn.featur ...
- Linux 安装分区设置分区大小
一.Linux分区挂载点介绍 Linux分区挂载点介绍,推荐容量仅供参考不是绝对,跟各系统用途以及硬盘空间配额等因素实际调整: 分区类型 介绍 备注 /boot 启动分区 一般设置100M-200M, ...
- vue+element-ui:table表格中的slot 、formatter属性
slot 插槽,table中表示该行内容以自定义方式展示 :formatter 方法,用来格式化内容 Function(row, column, cellValue, index) html < ...
- Linq.Expressions扩展ExpressionExtension
手上有一个以前项目用到的.NET工具类封装的DLL. 正好又想试一下动态LAMBDA表达式,用.NET Reflector看一下源码. public static class ExpressionEx ...
- Flink的状态与容错
本文主要运行到Flink以下内容 检查点机制(CheckPoint) 状态管理器(StateBackend) 状态周期(StateTtlConfig) 关系 首先要将state和checkpoint概 ...
- Spring Security,没有看起来那么复杂(附源码)
权限管理是每个项目必备的功能,只是各自要求的复杂程度不同,简单的项目可能一个 Filter 或 Interceptor 就解决了,复杂一点的就可能会引入安全框架,如 Shiro, Spring Sec ...