Kruskal vs Borůvka
做了个对比.Borůvka算法对于稠密图效果特别好.这两个都是求生成森林的算法.Prim+heap+tarjan过于难写不写了.
V=200,E=1000
Kruskal method
487504811
Time usage: 129 us
Bor(uc)uvka method
487504811
Time usage: 94 us
V=500,E=3000
Kruskal method
1068863143
Time usage: 431 us
Bor(uc)uvka method
1068863143
Time usage: 321 us
V=1000,E=10000
Kruskal method
1248132507
Time usage: 1626 us
Bor(uc)uvka method
1248132507
Time usage: 707 us
V=2000,E=50000
Kruskal method
1023451601
Time usage: 4444 us
Bor(uc)uvka method
1023451601
Time usage: 1781 us
V=5000,E=100000
Kruskal method
3177798955
Time usage: 8300 us
Bor(uc)uvka method
3177798955
Time usage: 3473 us
V=10000,E=300000
Kruskal method
4240792222
Time usage: 26751 us
Bor(uc)uvka method
4240792222
Time usage: 11332 us
V=10000,E=500000
Kruskal method
2548867302
Time usage: 45754 us
Bor(uc)uvka method
2548867302
Time usage: 18561 us
V=20000,E=1000000
Kruskal method
5166175346
Time usage: 92360 us
Bor(uc)uvka method
5166175346
Time usage: 38672 us
V=50000,E=1000000
Kruskal method
32391070642
Time usage: 96633 us
Bor(uc)uvka method
32391070642
Time usage: 54670 us
V=100000,E=1000000
Kruskal method
129350661440
Time usage: 101094 us
Bor(uc)uvka method
129350661440
Time usage: 79034 us
V=300000,E=2000000
Kruskal method
578989469565
Time usage: 229092 us
Bor(uc)uvka method
578989469565
Time usage: 208983 us
V=500000,E=6000000
Kruskal method
536707083899
Time usage: 689042 us
Bor(uc)uvka method
536707083899
Time usage: 654468 us
V=1000000,E=10000000
Kruskal method
1290266237257
Time usage: 1254349 us
Bor(uc)uvka method
1290266237257
Time usage: 1443208 us
V=5000000,E=50000000
Kruskal method
6456472043049
Time usage: 8274752 us
Bor(uc)uvka method
6456472043049
Time usage: 16565600 us
V=10000000,E=50000000
Kruskal method
25804619307783
Time usage: 10263962 us
Bor(uc)uvka method
25804619307783
Time usage: 18875336 us
这个Boruvka的写法不是最好的;但是链表动态删除的Boruvka会很长也就没有比较的意义了.
#define sizex 100000000
#include <cmath>
#include <cstdio>
#include <random>
#include <algorithm>
#include <malloc.h>
#include <sys/time.h>
using namespace std;
int *data,res;
long long mytic(){
long long result = 0.0;
struct timeval tv;
gettimeofday( &tv, NULL );
result = ((long long)tv.tv_sec)*1000000 + (long long)tv.tv_usec;
return result;
}
#define dic1() disA(generator)
#define dic2() disB(generator)
struct edge{int a,b,w;};
bool cmp(edge a,edge b){
return a.w<b.w;
}
#define foredge for(int i=0;i<gr.El;++i)
#define forvert2 for(int i=0;i<gr.N;++i)
#define eg gr.E[i]
struct graph{
int N,El;
edge E[50000000];
void sorter(){
sort(E,E+El,cmp);
}
void genData(int a,int b){
N=a;
El=b;
mt19937 generator;
uniform_int_distribution<int> disA(0,N-1);
uniform_int_distribution<int> disB(0,21474836);
for(int i=0;i<El;++i){
E[i].a=dic1();
while((E[i].b=dic1())==E[i].a);
E[i].w=dic2();
}
}
} gr;
struct ds_set{
int fa[10000000];
void clear(){
for(int i=0;i<gr.N;++i) fa[i]=-1;
}
int find(int p){return ~fa[p]?fa[p]=find(fa[p]):p;}
inline int merge(int a,int b){return (a==b)?(-1):(fa[b]=a);}
} ds;
#define ffind(a) ds.find(a)
#define funion(a,b) ds.merge(a,b)
struct algo_Kruskal{
long long run(){
long long ans=0;
gr.sorter();
int a,b;
foredge{
a=ffind(eg.a),b=ffind(eg.b);
ans+=~funion(a,b)?eg.w:0;
}
return ans;
}
} Kruskal;
struct algo_Boruvka{
struct v{
int a,p;
} vm[10000000];
long long run(){
long long ans=0;
int a,b,c,w;
while(1){
c=0;
forvert2 vm[i].a=100000000;
foredge{
w=eg.w,a=ffind(eg.a),b=ffind(eg.b);
if(a==b) continue;
++c;
if(w<vm[a].a) vm[a]={w,i};
if(w<vm[b].a) vm[b]={w,i};
}
if(!c) break;
forvert2 if(vm[i].a!=100000000) {
a=ffind(gr.E[vm[i].p].a);
vm[i].p=ffind(gr.E[vm[i].p].b);
ans+=(~funion(a,vm[i].p))?vm[i].a:0;
}
}
return ans;
}
} Boruvka;
FILE* loggar;
void testN(){
long long i;
printf("Kruskal method\n");
fprintf(loggar,"Kruskal method\n");
ds.clear();
long long start=mytic();
i=Kruskal.run();
start=mytic()-start;
printf("%lld\n",i);
printf("Time usage: %lld us\n",start);
fprintf(loggar,"%lld\n",i);
fprintf(loggar,"Time usage: %lld us\n",start);
}
void testU(){
long long i;
printf("Bor(uc)uvka method\n");
fprintf(loggar,"Bor(uc)uvka method\n");
ds.clear();
long long start=mytic();
i=Boruvka.run();
start=mytic()-start;
printf("%lld\n",i);
printf("Time usage: %lld us\n",start);
fprintf(loggar,"%lld\n",i);
fprintf(loggar,"Time usage: %lld us\n",start);
}
int as[15]={200 ,500 ,1000 ,2000 ,5000 ,10000 ,10000 ,20000 ,50000 ,100000 ,300000 ,500000 ,1000000 ,5000000 ,10000000};
int bs[15]={1000,3000,10000,50000,100000,300000,500000,1000000,1000000,1000000,2000000,6000000,10000000,50000000,50000000};
int main(){
int a,b,c,i,j,k,l,m,n,N,U,P,UP;
loggar=fopen("MSTTest.data","w");
for(int i=0;i<15;++i){
printf("%d %d\n",as[i],bs[i]);
fprintf(loggar,"V=%d,E=%d\n",as[i],bs[i]);
gr.genData(as[i],bs[i]);
testN(),testU();
}
fclose(loggar);
return 0;
}
过饱和稠密图上花样虐Kruskal
V=3000,E=50000000
Kruskal method
2305771
Time usage: 5808210 us
Bor(uc)uvka method
2305771
Time usage: 1270494 us
V=5000,E=50000000
Kruskal method
6381189
Time usage: 5789551 us
Bor(uc)uvka method
6381189
Time usage: 1274763 us
V=10000,E=50000000
Kruskal method
25291282
Time usage: 5834369 us
Bor(uc)uvka method
25291282
Time usage: 1654772 us
稀疏图大概比Kruskal慢一倍,花样虐Prim.
还有一个小花絮就是我弄错随机数生成范围Kruskal狂错不止.
Prim+pbdsheap还是有前途的,不过Boruvka完全够了.
两个长度加起来和不带堆的Prim一样了真不错.
Kruskal vs Borůvka的更多相关文章
- 【做题】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算法,利用优 ...
- Borůvka algorithm
Borůvka algorithm 我好无聊啊,直接把wiki的算法介绍翻译一下把. wiki关于Borůvka algorithm的链接:链接 Borůvka algorithm是一个在所有边权都是 ...
- Codeforces.888G.Xor-MST(Borůvka算法求MST 贪心 Trie)
题目链接 \(Description\) 有一张\(n\)个点的完全图,每个点的权值为\(a_i\),两个点之间的边权为\(a_i\ xor\ a_j\).求该图的最小生成树. \(n\leq2*10 ...
- Borůvka (Sollin) 算法求 MST 最小生成树
基本思路: 用定点数组记录每个子树的最近邻居. 对于每一条边进行处理: 如果这条边连成的两个顶点同属于一个集合,则不处理,否则检测这条边连接的两个子树,如果是连接这两个子树的最小边,则更新 (合并). ...
- bzoj2429- 聪明的猴子
题意其实就是说有很多个点,求一组边把它们都连接起来,并且最大的那条边最小.很明显这就是一个最小生成树,是一颗保证最长边最短的树. 代码 刚刚学了个Borůvka算法,于是写了两个. Borůvka # ...
- 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\) 次修改, ...
- 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用
图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...
随机推荐
- poj1703 并查集
输入是2个不在一起的人,可以用一个数组来保存和他矛盾的人.这样find的时候就find(hash[]);就可以: #include<stdio.h> #include<string. ...
- svn版本控制方案:多分支并行开发,多环境自动部署
背景 keywords:svn,trunk,branch,jenkins,maven,merge 两地同时开发一个产品,目前线上有3个环境:测试环境.预发布环境.生产环境.目前系统部署采用jenkin ...
- 学习笔记-动态树Link-Cut-Tree
--少年你有梦想吗? --少年你听说过安利吗? 安利一个集训队讲解:http://wenku.baidu.com/view/75906f160b4e767f5acfcedb 关于动态树问题,有多种方法 ...
- vim下使用ctags+taglist
好几年前用过,但是后来就生疏了,好其次都没法鼓起勇气再捡起来...今天不得不用,那既然捡起来了,就好好的记录一下. 简介及安装 ctags是一个应用程序,可以用它来生产当前目录下所有c文件中变量和函数 ...
- 数组添加:如何往数组的"null"位置插入数据呢?
数组添加,当已经存在的一个数组时,如何往数组的"null"位置插入数据呢? 分析: 1.循环遍历数组元素,找出null的位置(下标) 2.设置一个变量,接收null位置下标值 3. ...
- 单步调试 step into/step out/step over 区别
step into:单步执行,遇到子函数就进入并且继续单步执行(简而言之,进入子函数): step over:在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完再停止, ...
- DataTable列上多值运算
1.从网上找了个中缀算法(也不知道什么前缀后缀,抱歉),可以对字符串表达式进行运算 2.有些时候还是会用到ASCII码表的 char c = expression[k];//expression为一字 ...
- Sencha Touch 2.2.1 Custom Icon 自定义图标
ST2.2版本竟然又改变了sass中自定义图标的添加方式,在2.2以前采用的是这种base64的方式,详见:http://www.cnblogs.com/qidian10/archive/2012/1 ...
- Java基础之理解Annotation(与@有关,即是注释)
Java基础之理解Annotation 一.概念 Annontation是Java5开始引入的新特征.中文名称一般叫注解.它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata) ...
- WPF 窗体拖转时不触发MouseLeftButtonUpEvent
解决方案:手动添加Handler,因为e.Handled这个属性是用在路由事件中的,当某个控件得到一个RoutedEvent,就会检测Handled是否为true,为true则忽略该事件. //手动注 ...