【POJ3585】Accumulation Degree 二次扫描与换根法
简单来说,这是一道树形结构上的最大流问题。
朴素的解法是可以以每个节点为源点,单独进行一次dp,时间复杂度是\(O(n^2)\)
但是在朴素求解的过程中,相当于每次都求解了一次整棵树的信息,会做了不少的重复工作。
对于一棵子树的孩子节点和根节点之间存在着最优解的某些关联,因此可以采用自顶向下的一次 dfs 遍历求得结果。
阶段:子树大小
状态:当前子树大小的情况下,最大的流量是多少
状态转移方程:见代码
代码如下
#include <cstdio>
#include <vector>
#include <memory.h>
using namespace std;
const int maxn=2e5+10;
int n,rt,d[maxn],f[maxn],deg[maxn];
struct node{
int to,w;
node(int x=0,int y=0):to(x),w(y){}
};
vector<node> G[maxn];
#define cls(a,b) memset(a,b,sizeof(a))
void init(){
cls(d,0);cls(f,0);cls(deg,0);
for(int i=1;i<=2e5;i++)G[i].clear();
}
inline void add_edge(int from,int to,int w){
G[from].push_back(node(to,w)),++deg[from];
G[to].push_back(node(from,w)),++deg[to];
}
void read_and_parse(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int from,to,w;
scanf("%d%d%d",&from,&to,&w);
add_edge(from,to,w);
}
}
void dfs1(int u,int fa){
for(int i=0;i<G[u].size();i++){
int v=G[u][i].to,w=G[u][i].w;
if(v==fa)continue;
dfs1(v,u);
if(deg[v]==1)d[u]+=w;
else d[u]+=min(w,d[v]);
}
}
void dfs2(int u,int fa){
for(int i=0;i<G[u].size();i++){
int v=G[u][i].to,w=G[u][i].w;
if(v==fa)continue;
if(deg[u]==1)f[v]=d[v]+w;
else f[v]=d[v]+min(f[u]-min(w,d[v]),w);
dfs2(v,u);
}
}
void solve(){
rt=1;
dfs1(rt,0);
f[rt]=d[rt];//自顶向下需要初始化
dfs2(rt,0);
int ans=0;
for(int i=1;i<=n;i++)ans=max(ans,f[i]);
printf("%d\n",ans);
}
int main(){
int T;scanf("%d",&T);
while(T--){
init();
read_and_parse();
solve();
}
return 0;
}
【POJ3585】Accumulation Degree 二次扫描与换根法的更多相关文章
- POJ3585 Accumulation Degree(二次扫描与换根法)
题目:http://poj.org/problem?id=3585 很容易想出暴力.那么就先扫一遍. 然后得到了指定一个根后每个点的子树值. 怎么转化利用一下呢?要是能找出当前点的父亲的 “ 不含当前 ...
- poj3585 树形dp 二次扫描,换根法模板题
#include<iostream> #include<cstring> #include<cstdio> #include<vector> using ...
- 题解 poj3585 Accumulation Degree (树形dp)(二次扫描和换根法)
写一篇题解,以纪念调了一个小时的经历(就是因为边的数组没有乘2 phhhh QAQ) 题目 题目大意:找一个点使得从这个点出发作为源点,流出的流量最大,输出这个最大的流量. 以这道题来介绍二次扫描和换 ...
- poj 3585 Accumulation Degree(二次扫描和换根法)
Accumulation Degree 大致题意:有一棵流量树,它的每一条边都有一个正流量,树上所有度数为一的节点都是出口,相应的树上每一个节点都有一个权值,它表示从这个节点向其他出口可以输送的最大总 ...
- $Poj3585\ Accumulation Degree$ 树形$DP/$二次扫描与换根法
Poj Description 有一个树形的水系,由n-1条河道与n个交叉点组成.每条河道有一个容量,联结x与y的河道容量记为c(x,y),河道的单位时间水量不能超过它的容量.有一个结点是整个水系的发 ...
- 【51Nod1405】树上距离和 二次扫描与换根法
题目大意:给定一棵 N 个点的边权均为 1 的树,依次输出每个点到其他各个点的距离和. 题解:首先任意选定一个节点为根节点,比如 1,第一遍 dfs 遍历树求出子树大小.树上前缀和.第二遍 dfs 遍 ...
- poj - 3585(二次扫描与换根法)
周末牛客挂了个更难的,这个简单一些 #include<iostream> #include<cstring> #include<cstdio> #include&l ...
- [LuoguP1829]Crash的文明表格(二次扫描与换根+第二类斯特林数)
Solution: 由于 \[ x^m = \sum_{i=0}^m{~m~\choose i}{~x~\brace i}i! \] 将所求的式子化成这样,挖掘其性质,考虑是否能从儿子转移(或 ...
- poj3585 Accumulation Degree【树形DP】【最大流】
Accumulation Degree Time Limit: 5000MS Memory Limit: 65536K Total Submissions:3151 Accepted: 783 ...
随机推荐
- Linux运维笔记-日常操作命令总结(1)
在linux日常运维中,我们平时会用到很多常规的操作命令. 查看服务器的外网ip [root@redis-new01 ~]# curl ifconfig.me [root@redis-new01 ~] ...
- HTML 5 拖放
拖放(Drag 和 drop)是 HTML5 标准的组成部分. 拖放 拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. 拖放事件 1. ...
- linux-RPM安装
vh可写可不写
- Python学习笔记(二)——数据类型
1.数据类型 Python有五个标准的数据类型: Numbers(数字) String(字符串) List(列表) Tuple(元组) Dictionary(字典) 2.Python数字类型 Pyth ...
- 5.1 四则运算单元测试j
由于上个星期请假没上课,这个星期回来才知道作业,时间比较赶,个人能力又不足,作业质量不是很好 Calculator.java import java.util.Scanner; public clas ...
- WebPage设计专业术语
header footer master content placeholder breadcrumb 面包屑(breadcrumb)源于一个童话,在网站中就是一行层级属性链接组成的线性链接标示(我的 ...
- JQuery 操作 radio 被坑一例
.removeAttr('checked'); .prop('checked',false); .prop('checked',true); 与 .attr("checked",t ...
- [读书笔记]Linux命令行与shell编程读书笔记03 文件系统等
1. 文件系统的种类 ext ext2 ext3 ext4 JFS XFS 其中ext3 开始支持journal日志模式 与raid卡类似 有 数据模式 排序模式 以及回写模式 数据模式最安全 回写 ...
- Jquery 组 表单验证
<!DOCTYPE html><html lang="zh-cn"><head> <meta charset="utf-8&qu ...
- 转《canvas实现滤镜效果》
<code class="language-html"><html> <head> <style type="text/css& ...