当前位置: 首页 > 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.gsyq.cn/news/94491.html

相关文章:

  • 2025年“免费+付费”降AI工具组合使用指南,ai率降到15%
  • 软件工程选择题
  • java流程控制
  • python中的“内置函数”
  • 终极指南:快速搭建Gitea自托管Git服务
  • 根据实际体验,优先选择支持多轮修改、学术规范严格的平台更省心。
  • Vue脚手架快速搭建指南
  • CSS 选择器
  • 祝贺C++40周年
  • 毕业设计实战:基于SpringBoot的校友管理系统设计与实现,社交+招聘功能避坑指南!
  • 光伏电站并网后如何玩转虚拟同步机?储能如何优雅地削峰填谷?今天咱们用Simulink搭个实战模型,拆解光储联合系统中的三大核心技能
  • 互联网大厂Java求职者面试技术深度文章示例
  • python学习第6天
  • Electron应用自动更新与跨平台部署实战指南
  • 3步极速部署PLabel:智能标注系统的实战指南
  • 征程 6P/H 计算平台部署指南
  • EtherCAT 逐帧报文解析:EEPROM 读取与配置阶段
  • 实用指南:如何用 HTML 生成 PC 端软件
  • DevOps从入门到精通:企业级实战系列(二)——企业级代码管理策略深度解析
  • End.
  • CARLA自动驾驶仿真环境搭建与DEMO详解
  • 【Batch】提取文件名批量写入txt文件
  • Postman + DeepSeek:接口测试效率革命 - 自动化用例生成与断言编写
  • DevOps从入门到精通:企业级实战系列(一)——DevOps核心概念与价值解析
  • 【小沐杂货铺】基于Three.JS绘制三维海面/海洋/水面(WebGL / vue / react )
  • 本地私有知识库新选择:访答知识库的优势与数据分析
  • python —— types.MethodType —— 函数绑定
  • 震惊!这家外卖小程序供应商,竟让餐厅日订单暴涨300%!
  • 目标检测效率革命:新一代Transformer架构如何重塑检测性能边界
  • 智能销售助手设计V2