树上深度和问题 - 换根DP

news/2024/10/6 12:16:28

问题引出:

给出 \(n\) 个点的树,求出分别以不同的 \(i\) 为根时,所有结点深度的和,根节点的深度为 \(0\)

首先我们有个自然的暴力思路, 也就是以每个节点为根节点做一遍 \(dfs\) 这样的复杂度是 \(O(n^2)\) 级别的, 所以要进行优化
看下图:

我们首先假设每个节点具有点权, 明显这里的点权是 \(1\), 接着给出以下定义:

  • 定义 \(c_i\) 为点权, 这里为 \(1\)
  • 定义 \(ALL\) 为所有点权的和
  • 定义 \(size_u\) 为以 \(u\) 为根的子树内的点权和
    假设我们此时以及求出了 \(0\) 号节点的答案 \(dp_0\), 那么当我们要求 \(2\) 号节点时, 我们把这个树分成两部分, 很明显黄框框出的部分内部的所有的节点到根节点的距离都要增加一个 \(w_{0 → 2}\), 这里明显边权为 \(1\), 那么其答案应该增加 \((ALL - size_2) * w_{0→2}\) , 接着看红框部分, 明显的所有的节点距离根节点的都要减去边权, 所以答案还应该减去 \(size_2 * w_{0→2}\), 故 \(dp_2 = dp_0 + ALL - size_2 - size_2\), 同理可以递推出其它的节点, 时间复杂度为 \(O(n)\)
    代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10, mod = 1e9 + 7;
signed main()
{std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int n; cin >> n;int sum = 0;vector<int> c(n + 1);for(int i = 1; i <= n; i++) c[i] = 1, sum += c[i];vector<pair<int, int>> g[n + 1];for(int i = 1; i < n; i++){int a, b; cin >> a >> b;g[a].push_back({b, 1}), g[b].push_back({a, 1});}vector<int> dp(n + 1), sz(n + 1), dep(n + 1);function<void(int, int)> dfs1 = [&](int u, int fa) -> void{dp[1] += c[u] * dep[u], sz[u] = c[u];for(auto [x, y] : g[u]){if(x == fa) continue;dep[x] = dep[u] + y;dfs1(x, u);sz[u] += sz[x];     }};function<void(int, int, int)> dfs2 = [&](int u, int fa, int cur) -> void{dp[u] = cur;for(auto [x, y] : g[u]){if(x == fa) continue;int ndp = cur;ndp += (sum - sz[x]) * y - sz[x] * y;dfs2(x, u, ndp);}};dfs1(1, 0), dfs2(1, 0, dp[1]);for(int i = 1; i <= n; i++) cout << dp[i] << '\n';return 0;
}

变形题目

1. Minimize Sum of Distances

Minimize Sum of Distances
此时的点权就要变了, 但是其目的还是一样的, 按照我们的模板改一下点权就可以了, 此题还可以用重心来做, 直接求出重心也是可以的

重心代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10, mod = 1e9 + 7;
signed main()
{std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int n; cin >> n;vector<int> g[n + 1];for(int i = 1; i < n; i++){int a, b; cin >> a >> b;g[a].push_back(b), g[b].push_back(a);}int sum = 0;vector<int> c(n + 1);for(int i = 1; i <= n; i++) cin >> c[i], sum += c[i];int res = 0, root = 0;vector<int> dp(n + 1), ndp(n + 1);dp[0]= 1e18;function<void(int, int)> dfs1 = [&](int u, int fa) -> void{dp[u] = 0, ndp[u] = c[u];for(auto x : g[u]){if(x == fa) continue;dfs1(x, u);ndp[u] += ndp[x];dp[u] = max(dp[u], ndp[x]);}dp[u] = max(dp[u], sum - ndp[u]);if(dp[u] < dp[root]) root = u;};function<void(int, int, int)> dfs2 = [&](int u, int fa, int d) -> void{for(auto x : g[u]){if(x == fa) continue;dfs2(x, u, d + 1);res += c[x] * d;}};dfs1(1, 0), dfs2(root, 0, 1);// for(int i = 1; i <= n; i++) cerr << dp[i] << ' ' << ndp[i] << endl;cout << res << '\n';return 0;
}

换根 \(dp\) 代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10, mod = 1e9 + 7;
signed main()
{std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int n; cin >> n;vector<int> g[n + 1];for(int i = 1; i < n; i++){int a, b; cin >> a >> b;g[a].push_back(b), g[b].push_back(a);}int sum = 0;vector<int> c(n + 1);for(int i = 1; i <= n; i++) cin >> c[i], sum += c[i];vector<int> dp(n + 1), sz(n + 1);function<void(int, int, int)> dfs1 = [&](int u, int fa, int d) -> void{dp[1] += c[u] * d, sz[u] = c[u];for(auto x : g[u]){if(x == fa) continue;dfs1(x, u, d + 1);sz[u] += sz[x];     }};function<void(int, int, int)> dfs2 = [&](int u, int fa, int cur) -> void{dp[u] = cur;for(auto x : g[u]){if(x == fa) continue;int ndp = cur;ndp += sum - sz[x] * 2;dfs2(x, u, ndp);}};dfs1(1, 0, 0), dfs2(1, 0, dp[1]);cout << *min_element(dp.begin() + 1, dp.end()) << '\n';return 0;
}

下面的题只需要改改边权改改点权就可以了

2.[USACO10MAR] Great Cow Gathering G

[USACO10MAR] Great Cow Gathering G

3.Distance Sums 2

Distance Sums 2

4.Tree with Maximum Cost

Tree with Maximum Cost

5.[POI2008] STA-Station

[POI2008] STA-Station

6.Tree Painting

Tree Painting

7.「MXOI Round 1」城市

「MXOI Round 1」城市

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/68288.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

珂朵莉树(ODT)

前言 主要是一种暴力思想。。。 本文来自 wiki 与洛谷题解的整合。 应用 主要是应付随机数据(区间操作) 实现 有几个核心操作。 set实现方法 定义 struct node {intt l,r;//intt:long longmutable intt v;node(const intt &ll,const intt &rr,const intt &vv) : …

高效开发Maven架构设计图解/掌握项目工程自动化技巧(精通篇一)

Maven是一个项目管理和构建自动化工具,主要服务于基于Java的项目。它使用一个名为POM(Project Object Model)的XML文件来描述项目的构建过程、依赖、插件等信息。肖哥弹架构 跟大家“弹弹” 高并发锁, 关注公号回复 mvcc 获得手写数据库事务代码 欢迎 点赞,关注,评论。…

20222406 2024-2025-1 《网络与系统攻防技术》实验一实验报告

20222406 2024-2025-1 《网络与系统攻防技术》实验一实验报告 1.实验内容 本周深入学习了缓冲区溢出相关内容,收获颇丰。 一、理论知识学习学习了缓冲区溢出的基本知识,包括汇编语言,了解了常见的指令如mov(数据传送)、push(压栈)、pop(出栈)、call(调用函数)等的基…

Markdown格式学习

Markdown格式学习 掌握内容 标题:使用 # 来表示不同级别的标题,如 # 表示一级标题,## 表示二级标题 有序列表:使用数字加点来创建,如 1., 2.。 链接:使用 链接描述。 强调:使用 * 或 _ 来表示斜体(两边各一个),使用两个 ** 或 __ 来表示粗体。 表格:使用 | 和 - 来创…

免费在线音频转字幕网站 All In One

免费在线音频转字幕网站 All In One 利用 AI 将语音转成文本 使用 AI 为视频添加字幕 free online Speech to Text websites免费在线音频转字幕网站 All In One利用 AI 将语音转成文本 / 使用 AI 为视频添加字幕free online Speech to Text websites 每天三次免费https://turbo…

英璞来(imprai)LLMs企业级智能助理:让大语言模型应用触手可及

在这个信息爆炸的时代,人工智能和大数据技术正在改变我们的生活。而随着大语言模型的广泛应用,如何快速、高效地将这些模型集成到各种应用场景中,成为了一个亟待面对的问题。今天,我们要向您介绍一款名为英璞来(imprai)的开箱即用的企业级智能助理平台,它能够让您轻松获…

服贸会上的科技闪耀之星:璞华易研PLM系统引领产品研发潮流

2024年中国国际服务贸易交易会(以下简称为“服贸会”)于9月在北京盛大开幕,再次汇聚全球目光,共襄智慧服务的盛宴。本届服贸会秉承“全球服务、互惠共享”的核心理念,聚焦“共享智慧服务,共促开放发展”,为参会者搭建了一个集展览展示、洽谈推介、成果发布于一体的多元化…

璞华科技珠海采筑:通过SRM系统实现采购管理一体化和精细化

SRM供应商关系管理应该怎么做?如何实现采购管理一体化?近日,聚焦建材采购交易领域的服务商珠海采筑和SRM系统提供商璞华科技通过合作给出了一个现实的回答:通过SRM系统,聚焦使用者视角,以数据为主线,实现采购管理的一体化和精细化。 珠海采筑电子商务有限公司 珠海采筑电…