Borůvka MST算法
当我认为最MST(最小生成树)已经没有什么学的了,才发现世界上还有个这个kruskal和prim结合的玩意
Borůvka 运用并查集的思想,先将每一个初始点集初始化为有且只有自己的点集,然后每一次合并都从所有的独立集合出发,找到一条权值最小的(权值相同,则编号最小)连向其他集合的边,然后合并集合,很容易看出,每次合并都会使集合总数少一半,合并次数大致为log n
相比之下,Borůvka的合并次数要远远少于其他两个常用的MST算法,但是,毕竟不是一般情况下最快的,但是在求解一些个别的(例如边数多,点数较少的完全图)问题有奇效
luogu MST的例题,过不去,最后一个点会T,毕竟Borůvka是用来解决完全图的,并不是一般情况下最快的
1 #include "bits/stdc++.h"
2 using namespace std;
3 #define LL long long
4 const int N = 2e5 + 10;
5 int n,m;
6 int s[N],t[N],w[N];
7 struct Boruvka
8 {
9 int f[N],use_edge[N],best[N];
10 void init()
11 {
12 for(int i = 1;i <= n;i ++) f[i] = i,best[i] = 0;
13 for(int i = 1;i <= m;i ++) use_edge[i] = 0;
14 }
15 int find(int x)
16 {
17 return f[x] == x ? x : (f[x] = find(f[x]));
18 }
19 int better(int x,int y)
20 {
21 if(!y) return 1;
22 if(w[x] < w[y]) return 1;
23 return x < y;
24 }
25 LL get(void)
26 {
27 int merge=0;
28 LL sum=0;
29 while(merge != n - 1)
30 {
31 for(int i = 1;i <= m;i ++)
32 {
33 if(use_edge[i]) continue;
34 int x = find(s[i]),y = find(t[i]);
35 if(x == y) continue;
36 if(better(i,best[x])) best[x] = i;
37 if(better(i,best[y])) best[y] = i;
38 }
39 for(int i = 1;i <= n;i ++)
40 {
41 if(best[i]){
42 int x = find(s[best[i]]),y = find(t[best[i]]);
43 if(x != y){
44 use_edge[best[i]] = 1;
45 f[x] = y;
46 merge ++;
47 sum += w[best[i]];
48 }
49 best[i] = 0;
50 }
51 }
52 }
53 return sum;
54 }
55 }g;
56 int main(void)
57 {
58 ios::sync_with_stdio(false);
59 cin >> n >> m;
60 for(int i = 1;i <= m;i ++) cin >> s[i] >> t[i] >> w[i];
61 g.init();
62 cout << g.get() << '\n';
63 return 0;
64 }
很经典的题,题目大意为:
给定一个n个节点的完全图,每个节点有个编号ai,节点i和节点j之间边的权值为ai xor aj,求该图的最小生成树的权值和。
完全图,优先考虑Borůvka
需要在n log n左右的时间中求出每个连通块最小的连接的边,在这道题中边权可以通过点权求出
但是,这是不能直接算出每条边的边权的,因为这一看就是会超时的
所以根据二进制的性质,考虑建对全局建一个01trie,然后再给每一个连通块建一个tire,Borůvka算法每一次合并两个连通块,就合并两个tire,再在trie上维护子树的size,点权异或最小值就直接在全局trie与当前连通块的size作差得到树上贪心即可
总共会迭代log n次,总时间复杂度为O(n logn logsize ),空间复杂度为O(n log size)
code,仅供参考,没有注释
1 #include"bits/stdc++.h"
2 #define ll long long
3 #define inl inline
4 #define reg register
5 #define ls ch[now][0]
6 #define rs ch[now][1]
7 using namespace std;
8 const int N = 2e5 + 10;
9 const int inf = 0x7ffffff;
10
11 int L[N * 40],R[N * 40];
12 int ch[N * 40][2];
13 int tot;
14 int n,a[N],root;
15 inl int read(void)
16 {
17 int x = 0,f = 1;char ch = getchar();
18 while(!isdigit(ch)) f = ch == '-' ? - 1 : f,ch = getchar();
19 while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0',ch = getchar();
20 return x * f;
21 }
22 inl void Insert(int &now,int x,int dep)
23 {
24 if(!now) now = ++ tot;
25 L[now] = min(L[now],x),R[now] = max(R[now],x);
26 if(dep < 0) return;
27 int bit = a[x] >> dep & 1;
28 Insert(ch[now][bit],x,dep - 1);
29 }
30 inl int query(int now,int val,int dep)
31 {
32 if(dep < 0) return 0;
33 int bit = val >> dep & 1;
34 if(ch[now][bit]) return query(ch[now][bit],val,dep - 1);
35 else return query(ch[now][bit ^ 1],val,dep - 1) + (1 << dep);
36 }
37 inl ll dfs(int now,int dep)
38 {
39 if(dep < 0) return 0;
40 if(R[ls] && R[rs])
41 {
42 int minn = inf;
43 for(int i = L[ls];i <= R[ls];i ++) minn = min(minn,query(rs,a[i],dep - 1));
44 return dfs(ls,dep - 1) + dfs(rs,dep - 1)+ minn + (1 << dep);
45 }
46 if(R[ls]) return dfs(ls,dep - 1);
47 if(R[rs]) return dfs(rs,dep - 1);
48 return 0;
49 }
50 int main(void)
51 {
52 n = read();
53 for(int i = 1;i <= n;i ++) a[i] = read();
54 sort(a + 1,a + 1 + n);
55 memset(L,0x3f,sizeof(L));
56 for(int i = 1;i <= n;i ++) Insert(root,i,30);
57 printf("%lld\n",dfs(root,30));
58 return 0;
59 }
Borůvka MST算法的更多相关文章
- Borůvka (Sollin) 算法求 MST 最小生成树
基本思路: 用定点数组记录每个子树的最近邻居. 对于每一条边进行处理: 如果这条边连成的两个顶点同属于一个集合,则不处理,否则检测这条边连接的两个子树,如果是连接这两个子树的最小边,则更新 (合并). ...
- Codeforces.888G.Xor-MST(Borůvka算法求MST 贪心 Trie)
题目链接 \(Description\) 有一张\(n\)个点的完全图,每个点的权值为\(a_i\),两个点之间的边权为\(a_i\ xor\ a_j\).求该图的最小生成树. \(n\leq2*10 ...
- 【做题】CSA72G - MST and Rectangles——Borůvka&线段树
原文链接 https://www.cnblogs.com/cly-none/p/CSA72G.html 题意:有一个\(n \times n\)的矩阵\(A\),\(m\)次操作,每次在\(A\)上三 ...
- 最小生成树-Borůvka算法
一般求最小生成树的时候,最流行的是Kruskal算法,一种基于拟阵证明的贪心,通过给边排序再扫描一次边集,利用并查集优化得到,复杂度为\(O(ElogE)\).另一种用得比较少的是Prim算法,利用优 ...
- Kruskal vs Borůvka
做了个对比.Borůvka算法对于稠密图效果特别好.这两个都是求生成森林的算法.Prim+heap+tarjan过于难写不写了. V=200,E=1000 Kruskal method 4875048 ...
- Borůvka algorithm
Borůvka algorithm 我好无聊啊,直接把wiki的算法介绍翻译一下把. wiki关于Borůvka algorithm的链接:链接 Borůvka algorithm是一个在所有边权都是 ...
- 最小生成树MST算法(Prim、Kruskal)
最小生成树MST(Minimum Spanning Tree) (1)概念 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边,所谓一个 ...
- NOIp 图论算法专题总结 (1):最短路、最小生成树、最近公共祖先
系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 最短路 Floyd 基本思路:枚举所有点与点的中点,如果从中点走最短,更新两点间 ...
- 「CSA72」MST
「CSA72」MST 题目大意:有一个大小为 \(n\) 的无向完全图,\(x, y\) 之间的边权值为 \(a[\min(x,y)][\max(x,y)]\) ,初始为0,进行 \(m\) 次修改, ...
- 最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind
最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小 ...
随机推荐
- vetur 和 volar 不要一起装 - vscode插件 已解决
vetur 和 volar 不要一起装 - vscode插件 会有各种稀奇古怪的问题. 解决方案 利用 vscode 工作区 新建工作区 然后全局 将 volar 禁用工作区,起一个新的vue3项目, ...
- java多线程的锁整理
参考,欢迎点击原文:https://www.jianshu.com/p/473a3d96a1b0(java锁总结) https://www.jianshu.com/p/dcabdf695557(Ree ...
- K8S-1.23.17+Ceph+KubeSphere 一主二从部署攻略
K8S部署攻略 此教程以一主二从为例,需要三台服务器. 主机最低需求: 4 核 CPU,4 GB 内存,硬盘:20 GBx2 (需保留一个未分区的磁盘) 从机最低需求: 4 核 CPU,8 GB 内存 ...
- 【ATCOER、D - ±1 Operation 2】前缀和+排序二分
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Arrays; public cla ...
- SPSS安装及破解教程
SPSS是一种统计分析软件,其全称为"Statistical Product and Service Solutions".以下是SPSS的作用和好处: 作用: 数据管理:SPSS ...
- R语言安装教程
R 语言官方网站:The Comprehensive R Archive Network 官方镜像站列表:CRAN - Mirrors 一.官网下载R安装包 下载地址为:Index of /bin 进 ...
- DARTS:基于梯度下降的经典网络搜索方法,开启端到端的网络搜索 | ICLR 2019
DARTS是很经典的NAS方法,它的出现打破了以往的离散的网络搜索模式,能够进行end-to-end的网络搜索.由于DARTS是基于梯度进行网络更新的,所以更新的方向比较准确,搜索时间相当于之前的方法 ...
- 关于Guava Cache 需要注意的几点
一.元素过期策略 expireAfterWrite(long duration, TimeUnit unit):在元素[写入]或者[值更新]后的一段时间之后,自动移除元素. 当duration=0时, ...
- 性能对比 Go、Python、Perl、Ruby、Rust、C/C++、PHP、Node.js、Java.. 等多编
1. 有人说 Python 性能没那么 Low? 这个我用 pypy 2.7 确认了下,确实没那么差, 如果用 NumPy 或 其它版本 Python 的话,性能更快.但 pypy 还不完善,pypy ...
- Refresh Clean Code
这是一本被前辈称赞, 另一个马丁的知名著作, 被赋予学习如何写出漂亮代码的教皇级手册, 最近(再)浏览, 有诸多感受. 总结一下就是如果你是新手, 可能看优秀的open source学习更好; 如果你 ...