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条高速公路,保证了任意两运城市之间都可以通过高速公 ...
随机推荐
- NSPredicate实现数据筛选
一:基本语法 1.什么是NSPredicate apple官方文档这样写的: The NSPredicate class is used to define logical conditions us ...
- LeetCode刷题(持续更新ing……)
准备刷题了!已经预见未来的日子是苦并快乐的了!虽然 N 年前刷过题,但现在感觉数据结构与算法的基本功快忘光了
- ASP.NET Identity实现分布式Session,Docker+Nginx+Redis+ASP.NET CORE Identity
零.背景介绍 在学习ASP.NET CORE开发的过程中,身份认证是必须考虑的一项必要的组件.ASP.NET CORE Identity是由微软官方开发的一整套身份认证组件,兼具完整性和自由度.Doc ...
- hibernate.hbm.xml必须必须配置主键
hibernate.hbm.xml必须必须配置主键 <id name="XXid" type="java.lang.long" column=" ...
- 留学生如何在Presentation中拿高分?
掐指一算,留学生们最近应该马上遇到Presentation任务.一般来说,这类的任务会占最终成绩的20-30%,对于期末成绩有一定的影响,如果想拿高分,就需要好好的准备. 所以本文算是系列里的第一篇( ...
- [题解] LuoguP4381 [IOI2008]Island
LuoguP4381 [IOI2008]Island Description 一句话题意:给一个基环树森林,求每棵基环树的直径长度的和(基环树的直径定义与树类似,即基环树上一条最长的简单路径),节点总 ...
- Python win32api.keybd_event模拟键盘输入
win32api.keybd_event 该函数原型:keybd_event(bVk, bScan, dwFlags, dwExtraInfo) 第一个参数:虚拟键码(键盘键码对照表见附录): 第二个 ...
- Linux(CENTOS7) NodeJs安装
1.下载NodeJs 官网下载地址:http://nodejs.cn/download/ 2.上传到linux系统 我这里上传到/disk/nodejs目录下面的,上传工具使用的xftp. 3 ...
- hook鼠标键盘记录和回放
unit Unit1; // download by http://www.codefans.net interface uses Windows, Messages, SysUtils, Class ...
- LeetCode No.166,167,168
No.166 FractionToDecimal 分数到小数 题目 给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数. 如果小数部分为循环小数 ...