• 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
    ");
    	fprintf(loggar,"Kruskal method
    ");
    	ds.clear();
    	long long start=mytic();
    	i=Kruskal.run();
    	start=mytic()-start;
    	printf("%lld
    ",i);
    	printf("Time usage: %lld us
    ",start);
    	fprintf(loggar,"%lld
    ",i);
    	fprintf(loggar,"Time usage: %lld us
    ",start);
    }
    void testU(){
    	long long i;
    	printf("Bor(uc)uvka method
    ");
    	fprintf(loggar,"Bor(uc)uvka method
    ");
    	ds.clear();
    	long long start=mytic();
    	i=Boruvka.run();
    	start=mytic()-start;
    	printf("%lld
    ",i);
    	printf("Time usage: %lld us
    ",start);
    	fprintf(loggar,"%lld
    ",i);
    	fprintf(loggar,"Time usage: %lld us
    ",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
    ",as[i],bs[i]);
    		fprintf(loggar,"V=%d,E=%d
    ",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一样了真不错.

  • 相关阅读:
    line
    同步fifo的verilogHDL设计实例
    在DE1-SOC上运行Linux
    DE1-SOC连接设定
    Tcl语言笔记之二
    Tcl语言笔记之一
    关于复位赋初值的问题
    Altera FPGA中的pin进一步说明
    Altera FPGA中的pin简介
    笔记之Cyclone IV第一卷第四章Cyclone IV器件中的嵌入式乘法器
  • 原文地址:https://www.cnblogs.com/tmzbot/p/4603512.html
Copyright © 2020-2023  润新知