POJ 3585 Accumulation Degree【换根DP】
传送门:http://poj.org/problem?id=3585
题意:给定一张无根图,给定每条边的容量,随便取一点使得从这个点出发作为源点,发出的流量最大,并且输出这个最大的流量。
思路:最近开始做树形DP这部分的题,发现存图部分不是太会,这道题需要用到邻接表存图,不熟悉的朋友可以见我的另一篇博客:https://blog.csdn.net/weixin_43820920/article/details/98610704
言归正传,这道题算是换根DP的裸题了,就是先随便找一个点做为根结点(u),从这个根结点(u)出发,依次找到其叶子结点
的父亲结点的最大流量,然后在依次从下往上更新,即可得到,该根结点(u)的最大流量。但是题意并没有给我们指定结点,所
以这就需要我们的换根了。我们可以依次枚举该根结点的孩子结点(v),将它的孩子节点(v)假设为符合题意的结点,依次更新。
设为以x为根的子树中,把x作为源点,从x发出的流量的最大值,这个用dfs扫描一次即可得出。 状态转移方程:
设为以x作为整棵树的根得出的答案,也只要dfs再次扫描一次。 第一次dfs是以u为根扫描的所以即是
状态转移方程:
这个dfs是从上往下更新。更新结点时,由于其父节点
已知(并且假设其父结点不为叶节点),先假设
去除
这条子树时为
,则此时的
,即是上面的状态转移方程
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
using namespace std;
const int maxn = 200005;
int n;
int tot;
struct node
{
int to;
int next;
int w;
};
node edges[maxn << 1];
int deg[maxn];//结点的深度
int head[maxn];
//以x为根的子树中,把x作为源点,从x发出的流量的最大值
int d[maxn];
//以x作为整棵树的根得出的答案
int f[maxn];
//邻接表存图
void add_edges(int u, int v, int w)
{
edges[++tot].to = v;
edges[tot].w = w;
edges[tot].next = head[u];
head[u] = tot;
}
void init()
{
memset(deg, 0, sizeof(deg));
memset(head, 0, sizeof(head));
memset(f, 0, sizeof(f));
memset(d, 0, sizeof(d));
tot = 0;
}
void dfs1(int root, int fa)
{
d[root] = 0;
for(int i = head[root]; i; i = edges[i].next)
{
int v = edges[i].to;
if(v == fa)
continue;
else
{
dfs1(v, root);
if(deg[v] == 1)
d[root] += edges[i].w;
else
d[root] += min(d[v], edges[i].w);
}
}
}
void dfs2(int root, int fa)
{
for(int i = head[root]; i; i = edges[i].next)
{
int v = edges[i].to;
if(v == fa)
continue;
else
{
if(deg[root] == 1)
{
f[v] = d[v] + edges[i].w;
}
else
{
f[v] = d[v] + min(f[root] - min(edges[i].w, d[v]), edges[i].w);
}
dfs2(v, root);
}
}
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
init();
for(int i = 1; i < n; i++)
{
int x, y, v;
scanf("%d%d%d", &x, &y, &v);
add_edges(x, y, v);
add_edges(y, x, v);
deg[x]++;
deg[y]++;
}
if(n == 0 || n == 1)
{
cout << 1 << endl;
continue;
}
else
{
int root = 1;
dfs1(root, 0);//随便取一个点做为根结点
f[root] = d[root];
dfs2(root, 0);
int ans = 0;
for(int i = 1; i <= n; i++)
ans = max(ans, f[i]);
cout << ans << endl;
}
}
}
POJ 3585 Accumulation Degree【换根DP】的更多相关文章
- poj3585 Accumulation Degree(换根dp)
传送门 换根dp板子题(板子型选手 题意: 一棵树确定源点和汇点找到最大的流量(拿出一整套最大瘤板子orz ; int head[maxn],tot; struct node { int nt,to; ...
- poj 3585 Accumulation Degree(二次扫描和换根法)
Accumulation Degree 大致题意:有一棵流量树,它的每一条边都有一个正流量,树上所有度数为一的节点都是出口,相应的树上每一个节点都有一个权值,它表示从这个节点向其他出口可以输送的最大总 ...
- POJ3585:Accumulation Degree(换根树形dp)
Accumulation Degree Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3425 Accepted: 85 ...
- POJ 3585 Accumulation Degree
二次扫描与换根法 用于解决无根树,对于每一个节点作为根时都要统计 做法: 1.先以任意一个节点为根,做树形DP,保存每个节点的DP值 2.然后自上而下dfs,对于每个节点考虑以他为根的最大值 #inc ...
- POJ 3585 Accumulation Degree 题解
题面 一句话题意:找一个点使得,使得从这个点出发作为源点,发出的流量最大,输出这个最大的流量 这道题是换根法+二次扫描的模板: 首先若确定1为原点,那么可以写出dp方程:当v的度是1时, g[u]+= ...
- [算法学习] 换根dp
换根dp 一般来说,我们做题的树都是默认 \(1\) 为根的.但是有些题目需要计算以每个节点为根时的内容. 朴素的暴力:以每个点 \(u\) 作为 \(root\) 暴力dfs下去,复杂度\(O(n^ ...
- [BZOJ4379][POI2015]Modernizacja autostrady[树的直径+换根dp]
题意 给定一棵 \(n\) 个节点的树,可以断掉一条边再连接任意两个点,询问新构成的树的直径的最小和最大值. \(n\leq 5\times 10^5\) . 分析 记断掉一条边之后两棵树的直径为 \ ...
- 2018.10.15 NOIP训练 水流成河(换根dp)
传送门 换根dp入门题. 貌似李煜东的书上讲过? 不记得了. 先推出以1为根时的答案. 然后考虑向儿子转移. 我们记f[p]f[p]f[p]表示原树中以ppp为根的子树的答案. g[p]g[p]g[p ...
- 换根DP+树的直径【洛谷P3761】 [TJOI2017]城市
P3761 [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公 ...
随机推荐
- HDU - 4405 Aeroplane chess(期望dp)
题意:沿着x轴从0走到大于等于N的某处,每一步的步数由骰子(1,2,3,4,5,6)决定,若恰好走到x轴上某飞行路线的起点,则不计入扔骰子数.问从0走到大于等于N的某处的期望的扔骰子次数. 分析: 1 ...
- AD走圆弧走线
美式键盘: “shift + 空格”
- 13 ~ express ~ 后台页面的搭建
一, 后台路由文件 /router/admin.js var express = require('express') var router = express.Router() /** * 验证 ...
- tableau中图形分析相关设置
1.柱形堆叠图单元格顶部显示总计值(可通过参考线实现) 2.调节图形单元格的宽窄度 (ctrl + 右键/左键) 3.折线图预测区间 趋势区间线 分析中预测并不是针对所有的日期格式均其作用,比如日期格 ...
- iOS应用内跳转到指定系统设置页
APP的跳转: 通过[ [UIApplication sharedApplication] openURL:url]这种方法来实现的. iOS 10以后跳转设置页要用 [[UIApplication ...
- js 格式化时间日期
Date.prototype.format = function(format){ var o = { "M+" : this.getMonth()+1, //month &quo ...
- HZNU-ACM寒假集训Day9小结 倍增
LCA 倍增法求最近公共祖先 首先对于每个结点先进行dfs预处理它的深度,再记录下它们往父亲方向走2的0次,1次...k次步所到达的结点.在这里2的k次大于整棵树的最大深度. 预处理完后,需要查询两个 ...
- 关于torch.nn.Conv2d的笔记
先看一下CLASS有哪些参数: torch.nn.Conv2d( in_channels, out_channels, kernel_size, stride=1, padding=0, dilati ...
- Android自定义View——贝塞尔曲线实现水波纹效果
我们使用到的是Path类的quadTo(x1, y1, x2, y2)方法,属于二阶贝塞尔曲线,使用一张图来展示二阶贝塞尔曲线,这里的(x1,y1)是控制点,(x2,y2)是终止点,起始点默认是Pat ...
- Mac Eclipse 打包可执行jar文件
2 3 4 保存后 终端 cd 目录 java -jar xxxx.jar