补题链接:Here

一个树形水系,有 \(n\) 个结点,根结点称为源点,叶子结点称为汇点,每条边都有水量限制$C(x,y) \((\)x,y$ 为这条边的两个端点),源点单位时间流出的水量称为整个水系的流量,求以哪一个结点作为源点整个水系的流量最大。

首先得理解到这是一道“不定根”的树形DP问题,这类题目的特点是,给定一个树形结构,需要以每个结点为根进行一系列统计。我们一般通过两次扫描来求解此类问题:(也即:二次扫描与换根法

  • 第一次扫描时任选一个点为根,在“有根树”上执行一次“树形DP”,也就是在回溯时发生的、自底向上的状态转移。
  • 第二次扫描,从刚才选出的根出发,对整棵树执行一次DFS,在每次递归前进行自上而下的推导,计算出“换根”之后的解。

首先,我们任选一个结点 root ,然后树形DP一下,求出 \(D_{root}\) 数组( \(D[i]\) 表示在以 \(i\) 为根的子树中流量的最大值)。然后设 \(f_x\) 表示以 \(x\) 为源点,流向整个水系的最大流量,则显然 \(f_{root} = D_{root}\) 假设 \(f_x\) 已经求出,考虑其子结点 \(y\) ,则 \(f[y]\) 包含两部分:

  1. 从 \(y\) 流向以 \(y\) 为根的子树的流量,已经计算出来。
  2. 从 \(y\) 沿着到父节点 \(x\) 的河道,进而流向水系中其他部分的流量。

由题意可知,从 \(x\) 流向 \(y\) 的流量为 \(min(D_y,c_{x,y})\) ,所以从 \(x\) 流向除 \(y\) 以外其他部分的流量分量是其两者之差:\(f_x - min(D_y,c_{x,y})\) 于是,把 \(y\) 作为源点,先从流到 \(x\),再流向其他部分的流量就是吧这个“差值”再与 \(c_{x,y}\) 取较小值后的结果

\[if(deg[x] > 1) \to f[y] = D[y] + min(f[x] - min(D[y],c[x][y]) - c[x][y])\\
if(deg[x] == 1) \to f[y] = D[y] + c[x][y]
\]

这是一个由下而上的递推方程,所以我们可以通过一次DFS来完成

AC 代码

// Murabito-B 21/04/26
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
const int N = 2e5 + 5;
using pii = pair<int, int>;
vector<pii> g[N];
int dp[N], d[N], f[N];
void dfs(int u, int fa) {
for (int i = 0; i < g[u].size(); ++i) {
int v = g[u][i].fi, w = g[u][i].se;
if (v == fa) continue;
dfs(v, u);
if (d[v] == 1) dp[u] += w;
else
dp[u] += min(dp[v], w);
}
}
void dfs1(int u, int fa) {
f[u] = dp[u];
for (int i = 0; i < g[u].size(); ++i) {
int v = g[u][i].fi, w = g[u][i].se;
if (v == fa) continue;
if (d[v] == 1) {
dp[u] -= w;
dp[v] += min(dp[u], w);
} else {
dp[u] -= min(w, dp[v]);
dp[v] += min(w, dp[u]);
}
dfs1(v, u);
}
}
void solve() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
g[i].clear();
d[i] = dp[i] = f[i] = 0;
}
for (int i = 1; i < n; ++i) {
int u, v, w;
cin >> u >> v >> w;
g[u].push_back({v, w});
g[v].push_back({u, w});
d[u]++, d[v]++;
}
dfs(1, -1);
// f[1] = dp[1];
dfs1(1, -1);
int ans = 0;
for (int i = 1; i <= n; ++i) ans = max(ans, f[i]);
cout << ans << '\n';
}
int main() {
ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int _;
for (cin >> _; _--;) solve();
return 0;
}

【每日一题】14.Accumulation Degree(树形DP + 二次扫描)的更多相关文章

  1. $Poj3585\ Accumulation Degree$ 树形$DP/$二次扫描与换根法

    Poj Description 有一个树形的水系,由n-1条河道与n个交叉点组成.每条河道有一个容量,联结x与y的河道容量记为c(x,y),河道的单位时间水量不能超过它的容量.有一个结点是整个水系的发 ...

  2. poj3585 Accumulation Degree(树形dp,换根)

    题意: 给你一棵n个顶点的树,有n-1条边,每一条边有一个容量z,表示x点到y点最多能通过z容量的水. 你可以任意选择一个点,然后从这个点倒水,然后水会经过一些边流到叶节点从而流出.问你最多你能倒多少 ...

  3. poj3585 树形dp 二次扫描,换根法模板题

    #include<iostream> #include<cstring> #include<cstdio> #include<vector> using ...

  4. poj3585 Accumulation Degree[树形DP换根]

    思路其实非常简单,借用一下最大流求法即可...默认以1为根时,$f[x]$表示以$x$为根的子树最大流.转移的话分两种情况,一种由叶子转移,一种由正常孩子转移,判断一下即可.换根的时候由頂向下递推转移 ...

  5. SPOJ 1479 +SPOJ 666 无向树最小点覆盖 ,第二题要方案数,树形dp

    题意:求一颗无向树的最小点覆盖. 本来一看是最小点覆盖,直接一下敲了二分图求最小割,TLE. 树形DP,叫的这么玄乎,本来是线性DP是线上往前\后推,而树形DP就是在树上,由叶子结点状态向根状态推. ...

  6. CISP/CISA 每日一题 14

    CISA 每日一题(答) 自动无人值守运行(LIGHTS-OUT)优势:1.信息系统运行成本的遏制/减少:2.持续运行(24/7):3.减少系统错误和中断次数. I/O 控制人员负责保证:1.批处理信 ...

  7. UVA 10859 Placing Lamppost 树形DP+二目标最优解的求解方案

    题意:给定一个无向,无环,无多重边,要求找出最少的若干点,使得,每条边之中至少有一个点上有街灯.在满足上述条件的时候将还需要满足让两个点被选择的边的数量尽量多. 题解: 对于如何求解最小的节点数目这点 ...

  8. [树形DP]二叉苹果树

    二 叉 苹 果 树 二叉苹果树 二叉苹果树 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定 ...

  9. poj3417 Network 树形Dp+LCA

    题意:给定一棵n个节点的树,然后在给定m条边,去掉m条边中的一条和原树中的一条边,使得树至少分为两部分,问有多少种方案. 神题,一点也想不到做法, 首先要分析出加入一条边之后会形成环,形成环的话,如果 ...

  10. 『战略游戏 最大利润 树形DP』

    通过两道简单的例题,我们来重新认识树形DP. 战略游戏(luoguP1026) Description Bob喜欢玩电脑游戏,特别是战略游戏.但是他经常无法找到快速玩过游戏的办法.现在他有个问题.他要 ...

随机推荐

  1. windows server 2019 2012 server 2022 无线网卡驱动安装报错,无线网卡驱动不能安装, inf服务安装段落无效

    windows server 2019 无线网络 服务安装段落无效 windows server 2019 无线网卡驱动安装报错,无线网卡驱动不能安装, inf服务安装段落无效 indows serv ...

  2. antd Pro组件ProFormList实现自定义action

    antd Pro组件ProFormList实现自定义action ProFormList是ant design pro的结构化数据组件,通常用来实现动态表单. 现在有个需求,除了组件自带的删除和复制, ...

  3. 7-8次PTA和期末成绩总结

    (1)前言:总结之前所涉及到的知识点.题量.难度等情况 课程成绩统计程序-3在第二次的基础上修改了计算总成绩的方式(修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课 ...

  4. vertx的学习总结4之异步数据和事件流

    一.异步数据和事件流 1.为什么流是事件之上的一个有用的抽象? 2.什么是背压,为什么它是异步生产者和消费者的基础? 3.如何从流解析协议数据? 1.  答:因为它能够将连续的事件序列化并按照顺序进行 ...

  5. Apache POI 操作Excel简单入门使用

    Apache POI简介 开发中经常会涉及到excel的处理,如导出Excel,导入Excel到数据库中,操作Excel目前有两个框架,一个是apache 的poi, 另一个是 Java Excel ...

  6. .NET周刊 【12月第3期 2023-12-24】

    国内文章 CAP 8.0 版本发布通告 - CAP 7岁生日快乐! https://www.cnblogs.com/savorboard/p/cap-8-0.html 今天宣布CAP 8.0版本正式发 ...

  7. Dart 3.2 更新盘点

    作者 / Kevin Moore 和 Michael Thomsen 我们隆重宣布推出 Dart 3.2,这一版本针对以下方面做出了改进: 新增了一项语言功能,可对私有 final 字段进行非空升级: ...

  8. Spring表达式语言(SPEL)学习(01)

    算术运算 @Test public void test01() { // 定义解析器 ExpressionParser parser = new SpelExpressionParser(); // ...

  9. 【pandas小技巧】--目录(完结)

    pandas小技巧系列是介绍的是使用pandas分析数据时,最常用的一些操作技巧. 具体包括: 创建测试数据 学习pandas的过程中,为了尝试pandas提供的各类功能强大的函数,常常需要花费很多时 ...

  10. 编写一个小而强大的 Windows 动态屏保壁纸

    写在前面 两年前我做了第一个开源软件 DreamScene2 动态桌面,如今受到了很多人的喜欢,这增加了我继续做好开源软件的信心.之前的这个软件一直有人希望我加入一个设置屏保壁纸的功能,因为 Drea ...