当前位置: 首页 > news >正文

20251213 - 最小生成树

生成树

生成树,就是在一个无向连通图中选择 \(n - 1\) 条边,使得这 \(n-1\) 条边构成了一棵树。

最小生成树

假设每一条边有边权,边权和最小的生成树就是最小生成树(MST)。

求法

1. Prim

这是一个点核心的算法。

每次选择点权最小的点,在扩展到邻居节点,这和 dijkstra 几乎一毛一样。

朴素时间复杂度:\(O(n^2+m)\)

堆优化:\(O((n+m)\log_2m)\)

平衡树优化(实测更快一点):\(O((n+m)log_2m)\)

代码:

int Prim() {int ans = 0;priority_queue <Node> q;vector <int> dist(n + 1, inf), vis(n + 1, 0);dist[s] = 0;q.push({s, 0});while (!q.empty()) {int u = q.top().v, w = q.top().w;q.pop();if (vis[u]) continue;vis[u] = 1;ans += w;for (auto nxt : edges[u]) {int v = nxt.v, w = nxt.w;if (w < dist[v]) {dist[v] = w;q.push({v, dist[v]});}} }return ans;
}

2.kruskal

这是一个边核心的算法。

每次选择边权最小的边,在判断有没有环。

怎么判断有没有环呢?

Tarjan DSU!

代码:

int kruskal() {vector <TreeNode> edges;n = read(), m = read();for (int i = 1; i <= n; i++) fa[i] = i;for (int i = 1; i <= m; i++) {int x = read(), y = read(), w = read();edges.push_back({x, y, w});}sort(edges.begin(), edges.end());int ans = 0, tot = 0;;for (auto [x, y, w] : edges) { // C++17x = find(x), y = find(y);if (x != y) {fa[x] = y;ans += w;tot++;}} 
}

例题:

C - 营救

跑一下 kruskal,如果 find(s) == find(t) 直接输出即可。

#include <bits/stdc++.h>using namespace std;
#define ll long long
#define ull unsigned long long
#define db double
#define sz(x) ((int)x.size())
#define inf (1 << 30)
#define pb push_back
typedef pair<int, int> PII;
const int N = 1e5 + 7;
const int P = 998244353;
int read() {int x = 0, f = 1;char ch = getchar();while (!(ch >= '0' && ch <= '9')) {if (ch == '-') f = -f;ch = getchar();}while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}
int n, m, fa[N], s, t;
struct TreeNode {int x, y, w;bool operator < (const TreeNode &A) const {return w < A.w;}
};
vector <TreeNode> edges;
int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);
}
int main() {n = read(), m = read(), s = read(), t = read();for (int i = 1; i <= n; i++) fa[i] = i;for (int i = 1; i <= m; i++) {int x = read(), y = read(), w = read();edges.push_back({x, y, w});}sort(edges.begin(), edges.end());int ans = inf, tot = 0;;for (auto [x, y, w] : edges) {x = find(x), y = find(y);if (x != y) {fa[x] = y;tot++;if (find(s) == find(t)) {ans = min(ans, w);}}} printf("%d\n", ans);return 0;
}

D - Out of Hay S

就是求一个 max 即可。

E - 买礼物

把每一个优惠边权设成 A,再把不优惠连向 0 号点,再搞一遍 MST。

后记

警钟敲烂:在写并查集时请不要带 \(\log\)!!!

http://www.rkmt.cn/news/94491.html

相关文章:

  • Portfolio个人作品集网站:5分钟快速搭建专业在线简历终极指南
  • ComfyUI-SeedVR2视频超分项目FP8量化技术深度解析
  • 2025年降AI率工具实测!5个降AI工具推荐:免费降AIGC工具指南
  • Halo博客系统审计
  • tk.simpledialog-创建简单的模态对话框
  • STranslate 翻译 工具 v2.0.0 绿色便携版 翻译、OCR工具
  • 终极指南:免费获取卓里奇数学分析教材PDF完整资源
  • 毕业设计实战:基于SSM+MySQL的校园外卖服务系统设计与实现,从需求到上线全流程指南!
  • Pyperclip终极指南:3分钟掌握Python跨平台剪贴板操作
  • COMSOL模拟锌离子电池锌负极电场模型教程:从零开始构建并详细解析源文件,适合初学者的电场建模教学
  • 5分钟掌握LIBERO:开启终身机器人学习的革命性平台
  • Zigpy:Python驱动的智能家居Zigbee通信解决方案
  • Gleam语言深度解析:类型安全与跨平台编程的新范式
  • 解决Ubuntu/Linux/Gnome 打开文件慢,使用chrome打开文件更慢/卡死问题
  • Capacitor跨平台开发终极指南:用Web技术构建原生应用
  • 终极指南:如何用PIKE-RAG打造领域专属的智能问答系统
  • 009.数组排序
  • JavaEE:多线程基础,多线程的创建和用法 - 实践
  • 8051U深度入门到32位51大型实战
  • 吐血整理,装修前的灵魂拷问!口碑炸裂的装修公司大盘点 - 品牌测评鉴赏家
  • Claude提示工程核心技巧与程序员实战指南
  • renren-fast-vue 企业级后台管理系统开发实战指南
  • 面试手撕排序
  • 800+高质量Unity材质球:游戏开发的视觉宝藏
  • 基于深度学习的木薯病害检测系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
  • 考研路茫茫――单词情结
  • 二手房翻新不踩坑!2025年这些靠谱公司帮你焕新家 - 品牌测评鉴赏家
  • 2025苏州毛坯房装修攻略:这5家专业公司让毛坯变美宅不踩坑 - 品牌测评鉴赏家
  • 风-储系统仿真模型;通过模糊逻辑控制策略驱动蓄电池变换器运行,以达到为电网提供惯量的目的
  • 003HTML