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一样了真不错.

posted @ 2015-06-27 00:31  zball  阅读(453)  评论(0编辑  收藏  举报