Boruvka 算法
Boruvka算法解决某些问题超级好用。
这些问题形如,给你n个点,每个点有点权,任意两个点之间有边权,边权为两个点权用过某种计算方式得出。
求最小生成树。
通常用 \(O(log n)\) 的时间可以找到与点i连边的边权最小的j。
我们考虑这样一个求最小生成树的算法:
考虑维护当前的连通块(初始每个点为独立的一个连通块)
对每个连通块,找到一条与该连通块相连的,且另一端点不在此连通块中的边权最小的边。
将所有的这些边都加入最小生成树,注意,当加入一条边时需判断该边的两端点是否在同一连通块。
重复若干遍上述操作,直到图连通。
这个算法叫Boruvka算法。
复杂度分析:每次连通块个数至少减半,则复杂度为 \(O((n+m)logn)\) ,还有个并查集假装是 \(O(1)\)
但是此算法通常不用于求裸的最小生成树(Kruskal多好用)
可是在解决上述问题时,往往有奇效。
我们发现,我们只需要求出与每个连通块相连的边权最小的边即可,在这种类型的题目中,这个东西复杂度一般为 \(O(n log n)\)
所以我们就可以在 \(O(n log^2 n)\) 的复杂度下解决此类问题。
CF888G Xor-MST
给定 \(n\) 个结点的无向完全图。每个点有一个点权为 \(a_i\)。连接 \(i\) 号结点和 \(j\) 号结点的边的边权为 \(a_i\oplus a_j\)。
求这个图的多生成树的权值。
\(1\le n\le 2\times 10^5\),\(0\le a_i< 2^{30}\)。
/*header*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#define rep(i , x, p) for(int i = x;i <= p;++ i)
#define sep(i , x, p) for(int i = x;i >= p;-- i)
#define gc getchar()
#define pc putchar
#define ll long long
#define mk make_pair
#define fi first
#define se second
using std::min;
using std::max;
using std::swap;
const int inf = 0x3f3f3f3f;
const int maxN = 5000 + 7;
const int maxM = 200000 + 7;
inline int gi() {
int x = 0,f = 1;char c = gc;
while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}return x * f;
}
struct Node {
int u , v, w;
}Map[maxM];
int n , m;
int f[maxN];
bool vis[maxM];//该边是否用过
int d[maxN] , a[maxN];//各子树的最小连外边的权值
int id[maxN];// 记录各子树的最小连外边的编号
int find(int x) {return f[x] == x ? x : f[x] = find(f[x]);}
int unqie(int x , int y) {f[find(x)] = find(y);}
int Boruvka() {
for(int i = 1;i <= n;++ i) f[i] = i;
int sum = 0;
while(true) {
bool flag = false;
for(int i = 1;i <= n;++ i) d[i] = inf;
for(int i = 1;i <= m;++ i) {
int u = find(Map[i].u) , v = find(Map[i].v), c = a[u] & a[v];
if(u == v) continue;
flag = true;
if(c < d[u] || (d[u] == c && id[u] > i)) id[u] = i , d[u] = c;
if(c < d[v] || (d[v] == c && id[v] > i)) id[v] = i , d[v] = c;
}
if(!flag) break;
for(int i = 1;i <= n;++ i) {
if(d[i] != inf && !vis[id[i]]) {
unqie(Map[id[i]].u , Map[id[i]].v);
sum += Map[id[i]].w;
vis[id[i]] = true;
}
}
}
int tot = 0;
for(int i = 1;i <= n;++ i) if(f[i] == i) tot ++;
tot > 1 ? printf("orz") : printf("%d",sum);
}
int main() {
n = gi();m = gi();
for(int i = 1;i <= m;++ i) {
int u = gi() , v = gi(), w = gi();
Map[i] = (Node) {u , v, w};
}
Boruvka();
return 0;
}
Boruvka 算法的更多相关文章
- 最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind
最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小 ...
- 洛谷P3366 【模板】最小生成树(Boruvka算法)
题意 题目链接 Sol 自己yy着写了一下Boruvka算法. 算法思想很简单,就是每次贪心的用两个联通块之间最小的边去合并. 复杂度\(O(n \log n)\),然鹅没有Kruskal跑的快,但是 ...
- Boruvka算法求最小生成树
学习了一个新的最小生成树的算法,Boruvka(虽然我不知道怎么读).算法思想也是贪心,类似于Kruskal. 大致是这样的,我们维护图中所有连通块,然后遍历所有的点和边,找到每一个连通块和其他连通块 ...
- boruvka算法
算法正确性证明: 1.最优性:最小边一定包含在生成树中. 2.合法性:一定不会构成环.如果存在环说明一个点的最小连边有两个,显然矛盾. 算法时间复杂度证明: 每执行一次算法,所有联通块的大小都至少为2 ...
- 最小生成树---Prim算法和Kruskal算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
- 转载:最小生成树-Prim算法和Kruskal算法
本文摘自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html 最小生成树-Prim算法和Kruskal算法 Prim算 ...
- 最小生成树之Prim算法,Kruskal算法
Prim算法 1 .概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gr ...
- 《算法》第四章部分程序 part 15
▶ 书中第四章部分程序,包括在加上自己补充的代码,Kruskal 算法和 Boruvka 算法求最小生成树 ● Kruskal 算法求最小生成树 package package01; import e ...
- 最小生成树 Prim(普里姆)算法和Kruskal(克鲁斯特尔)算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
- prim 算法和 kruskal算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
随机推荐
- Linux-用户管理命令(必须是超级管理员-root)
useradd [名字] 创建一个新用户 (home 下创建) useradd -d [路径][名字] 路径中的名字是文件 , 登录用的后面的名字 passwd [用户名] 设置密码, ...
- 显示Label标签
1 from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout 2 from PyQt5.QtCore import ...
- python 打包模块:nuitka
该模块可以将python编译成C++级的可执行文件,是解决python图形化界面启动慢的神器. 1.环境配置 配置c/c++编译器:MinGW64 ,最低使用8.1版本,该资源自行下载. 百度网盘链接 ...
- MISC杂项解题思路
首先拿到一个杂项的附件 第一步要判断 是什么类型的杂项题目 附件是什么内容 是图片? 是压缩包? 是磁盘文件? 还是其他未知的东西 第一步的判断能够直接将解题思路精准定位到正确的区域下 加快解题速度 ...
- [jmeter]简介与安装
简介 JMeter是开源软件Apache基金会下的一个性能测试工具,用来测试部署在服务器端的应用程序的性能. 安装 安装jmeter 从 官网 下载jmeter的压缩包 安装jdk并配置 JAVA_H ...
- 【go笔记】标准库-strings
标准库-strings 前言 标准库strings用于处理utf-8编码的字符串. 字符串比较-Compare func Compare(a,b string) int 若 a==b ,则返回0:若 ...
- quarkus依赖注入之九:bean读写锁
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇是<quarkus依赖注入> ...
- Lithosphere是什么,它解决什么问题?
这问题很好,一针见血,它解决什么问题? 那这得说说,在IoT应用中,我们会碰到什么问题? 和纯软件项目,互联网项目比,IoT应用项目一个比较大不同的地方,应该是它既要做软件,又要做硬件. 我并不是硬件 ...
- 一张图读懂TuGraph Analytics开源技术架构
TuGraph Analytics(内部项目名GeaFlow)是蚂蚁集团开源的分布式实时图计算引擎,即流式图计算.通过SQL+GQL融合分析语言对表模型和图模型进行统一处理,实现了流.批.图一体化计算 ...
- 《Linux基础》07. 软件管理
@ 目录 1:软件管理 1.1:rpm 1.1.1:查询 1.1.2:卸载 1.1.3:安装 1.2:yum 1.3:dpkg 1.4:apt 1.4.1:相关配置 1.4.2:常用指令 1.4.3: ...