专栏文章
Boruvka 算法学习笔记
算法·理论参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minz7kj6
- 此快照首次捕获于
- 2025/12/02 10:45 3 个月前
- 此快照最后确认于
- 2025/12/02 10:45 3 个月前
介绍
Boruvka 算法相当于多源的 Prim。我们维护若干个块。
刚开始 中没有边,每个点都是一个块。
在每轮算法中:
- 找到每个块的最小边(最小的向外连的边)。
- 一次尝试连接每个最小边。
算法进行 轮。
算法的具体复杂度取决于求最小边的方式,这是根据题目而定的。对于模板题,一种简单的方式是 地扫描每个边。
这个并查集过程又很像 Kruskal,但 Boruvka 不需要排序。
CPP#include <bits/stdc++.h>
#define int long long
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define _rep(i, l, r) for (int i = (l); i >= (r); i--)
using namespace std;
constexpr int N = 5010, M = 2e5 + 10;
struct Edge {
int u, v, w;
} e[M];
int n, m;
int mn[N];
int fa[N], rk[N];
void init() {
rep (i, 1, n) fa[i] = i;
}
int find(int x) {
if (x == fa[x]) return x;
return fa[x] = find(fa[x]);
}
bool merge(int x, int y) {
int fx = find(x), fy = find(y);
if (fx == fy) return 0;
if (rk[fx] < rk[fy]) fa[fx] = fy;
else if (rk[fx] > rk[fy]) fa[fy] = fx;
else fa[fy] = fx, rk[fx]++;
return 1;
}
int Boruvka() {
init();
int res = 0;
for (;;) {
memset(mn, 0, sizeof(mn));
rep (i, 1, m) {
int u = e[i].u, v = e[i].v, w = e[i].w;
int fu = find(u), fv = find(v);
if (fu == fv) continue;
if (!mn[fu] || e[mn[fu]].w > w) mn[fu] = i;
if (!mn[fv] || e[mn[fv]].w > w) mn[fv] = i;
}
bool flag = 0;
rep (i, 1, n) {
if (fa[i] != i || mn[i] == 0) continue;
flag = 1;
int u = e[mn[i]].u, v = e[mn[i]].v, w = e[mn[i]].w;
if (merge(u, v)) res += w;
}
if (!flag) break;
}
return res;
}
signed main() {
cin >> n >> m;
rep (i, 1, m) {
int u, v, w;
cin >> u >> v >> w;
e[i] = {u, v, w};
}
int cnt = 0, res = Boruvka();
rep (i, 1, n) cnt += find(i) == i;
if (cnt == 1) cout << res;
else cout << "orz";
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...