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 算法的更多相关文章

  1. 最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind

    最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小 ...

  2. 洛谷P3366 【模板】最小生成树(Boruvka算法)

    题意 题目链接 Sol 自己yy着写了一下Boruvka算法. 算法思想很简单,就是每次贪心的用两个联通块之间最小的边去合并. 复杂度\(O(n \log n)\),然鹅没有Kruskal跑的快,但是 ...

  3. Boruvka算法求最小生成树

    学习了一个新的最小生成树的算法,Boruvka(虽然我不知道怎么读).算法思想也是贪心,类似于Kruskal. 大致是这样的,我们维护图中所有连通块,然后遍历所有的点和边,找到每一个连通块和其他连通块 ...

  4. boruvka算法

    算法正确性证明: 1.最优性:最小边一定包含在生成树中. 2.合法性:一定不会构成环.如果存在环说明一个点的最小连边有两个,显然矛盾. 算法时间复杂度证明: 每执行一次算法,所有联通块的大小都至少为2 ...

  5. 最小生成树---Prim算法和Kruskal算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

  6. 转载:最小生成树-Prim算法和Kruskal算法

    本文摘自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html 最小生成树-Prim算法和Kruskal算法 Prim算 ...

  7. 最小生成树之Prim算法,Kruskal算法

    Prim算法 1 .概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gr ...

  8. 《算法》第四章部分程序 part 15

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,Kruskal 算法和 Boruvka 算法求最小生成树 ● Kruskal 算法求最小生成树 package package01; import e ...

  9. 最小生成树 Prim(普里姆)算法和Kruskal(克鲁斯特尔)算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

  10. prim 算法和 kruskal算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

随机推荐

  1. 二进制安装K8S

    参考链接:https://zhuanlan.zhihu.com/p/408967897 准备工作 3台Centos7.9虚拟机 虚拟机配置:2C4G,能连接外网 虚机规划 ip 用途 192.168. ...

  2. 关于在Java中计算某个数的N次方注意事项

    在实际过程中,我们会遇到计算某个数的N次方的情景,在书面上我们是可以记作 a^n ,然而在Java中我们却不能这样使用,因为在Java中,这样的写法是位运算,即 假设 A = 60, B = 13,他 ...

  3. vlan与单臂路由

    vlan 1,什么是vlan vlan叫做虚拟局域网 (VLAN, Virtual LAN) 虚拟局域网(VLAN)是一组逻辑上的设备和用户,这些设备和用户并不受物理位置的限制,可以根据功能.部门及应 ...

  4. 工具—批量备案信息查询并生成fofa查询语句

    描述: 1.可以输入一个或多个公司名或域名或备案号,得到备案信息(备案公司名,备案公司网站url,备案号,域名类型,审核时间) 2.读取生成的信息并转为fofa语句,方便了指定目标的信息收集速度 工具 ...

  5. API接口的重要性

    API接口的重要性在现代软件开发中无可替代.以下是API接口的几个重要方面: 1. 实现系统集成:API接口允许不同应用程序之间实现数据共享和交流.通过API接口,不同的软件系统可以相互连接和协作,实 ...

  6. 使用flask开发web应用

    Flask环境搭建 要开发flash应用,我们需要做一些准备工作 我写了个初始化的脚本 Pip_init.sh来安装初始工作 可以到我的git上去下载该脚本进行初始化安装 要启动flask应用,我们需 ...

  7. 第3章 Git最最常用命令大全

    相信来查命令的同学,根本不是来学具体某个命令的作用的,只是想来查看命令的语法,博主深知这一点(因为博主也是这样过来的),相信这篇文章,将会带给你在工作中最常用的命令,让你一打开就是命令大全!! 喜欢这 ...

  8. 二叉树(binary tree)

    二叉树(binary tree) 二叉树(Binary Tree)是一种常见的树状数据结构,它由一组节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点.二叉树具有以下特点: 每个节点最多有 ...

  9. 从DevOps实践落地的角度谈谈“流程”和“规范"的反模式

    最近在经历的一些事情,让我突发灵感,觉得要写点关于DevOps体系建设过程中的"流程规范",记录下来. 如何解读"流程规范" 谈到DevOps落地,无一例外都会 ...

  10. Linux/Unix-CPU-SuperPI-Unixbench性能测试

    测试服务器CPU单核及多核SuperPI圆周率测试real和user值,SuperPI是利用CPU的浮点运算能力来计算出π(圆周率),测试系统稳定性和测试CPU计算完后特定位数圆周率所需的时间:及Un ...