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[ ...
随机推荐
- 【Flutter】功能型组件之颜色和主题
前言 Color类中颜色以一个int值保存,显示器颜色是由红.绿.蓝三基色组成,每种颜色占8比特,存储结构如下: Bit(位) 颜色 0-7 蓝色 8-15 绿色 16-23 红色 24-31 Alp ...
- 【Flutter】可滚动组件之SingleChildScrollView
前言 SingleChildScrollView类似于Android中的ScrollView,它只能接收一个子组件. 接口描述 const SingleChildScrollView({ Key ke ...
- 剑指Offer58-左转字符串
题目 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S=" ...
- sap alv grid 中的delete按键问题
今天发先一个问题,在使用ALV输出的时候,如果有字段设置为可编辑状态,则会在前面出现选择条,并且,当我们选择一行或者多行的时候,可以用键盘上的DELETE键将行删除!呵呵
- EFCore 5 新特性 —— Savepoints
EFCore 5 中的 Savepoints Intro EFCore 5中引入了一个新特性,叫做 Savepoints,主要是事务中使用,个人感觉有点类似于 Windows 上的系统还原点,如果事务 ...
- SpringMVC下关于静态资源访问
SpringMVC静态资源访问 聊一聊关于静态资源的访问问题 首先,我们要对web.xml里面的DispatcherServlet进行设置 <!-- 中央调度器--> <servle ...
- CSS3+JS完美实现放大镜模式
最近看到一篇讲放大镜的文章,实践后感觉效果非常好,这里分享给大家. 效果如下: 其实现核心: CSS函数,如:calc() -- 动态计算:var() -- 使用自定义变量 CSS伪元素:::befo ...
- FastAPI实践项目:SayHello(FastAPI + vue.js + axios + element ui)
目录 简介 翻版 VS 本尊 后端服务 源码 接下来 简介 这次带来的是FastAPI + vue.js + axios + element ui (一个html文件里使用的) 实现的<Flas ...
- C++ Primer Plus读书笔记(九)内存模型和名称空间
1.作用域和链接 int num3; static int num4; int main() { } void func1() { static int num1; int num2; } 上边的代码 ...
- v-modal的使用。
v-model用于表单数据的双向绑定,其实它就是一个语法糖,这个背后就做了两个操作:v-bind绑定一个value属性:v-on指令给当前元素绑定input事件.