• Boruvka


    大概是这样的:一开始图中有(n)个连通块,每次操作我们选出各个连通块连出去的最短的边(如果有相同边权的边的话可以把序号作为第二关键字),然后把这些边加入最小生成树。
    最坏的情况下每次操作都会让当前的连通块减半,因此Boruvka算法的复杂度为(O(mlog n))
    主要的应用在于边数为(O(n^2))级别但是有特殊性质(如曼哈顿距离、异或等)的情况,选各个连通块连出去的边的时候可以不枚举每条边而是直接找。

    #include<bits/stdc++.h>
    const int N=5007,M=200007;
    struct edge{int u,v,w;}e[M];
    int vis[M],a[N],fa[N];
    int read(){int x;scanf("%d",&x);return x;}
    int cmp(int i,int j){return !j? 1:(e[i].w<e[j].w||(e[i].w==e[j].w&&i<j));}
    int Find(int x){return x==fa[x]? x:fa[x]=Find(fa[x]);}
    int main()
    {
        int n=read(),m=read(),i,cnt=1,sum=0,f=1,u,v;
        for(i=1;i<=m;++i) e[i]=(edge){read(),read(),read()};
        for(i=1;i<=n;++i) fa[i]=i;
        while(f)
        {
    	f=0,memset(a,0,sizeof a);
            for(i=1;i<=m;++i)
    	{
    	    if(vis[i]||(u=Find(e[i].u))==(v=Find(e[i].v))) continue;
    	    if(cmp(i,a[u])) a[u]=i;
    	    if(cmp(i,a[v])) a[v]=i;
            }
            for(i=1;i<=n;++i)
                if(a[i]&&!vis[a[i]])
    		f=1,++cnt,sum+=e[a[i]].w,vis[a[i]]=1,fa[Find(e[a[i]].u)]=Find(e[a[i]].v);
        }
        cnt==n? printf("%d",sum):puts("orz");
    }
    
  • 相关阅读:
    mysql
    Linux下的C语言基础-4
    Linux下的C语言基础-3
    Linux下的C语言基础-2
    Linux下的C语言基础-1
    LeetCode:1375. 灯泡开关 III
    Jenkins+robotframework持续集成环境(三)
    Jenkins+robotframework持续集成环境(二)
    Jenkins+robotframework持续集成环境(一)
    robotframework操作使用
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11829067.html
Copyright © 2020-2023  润新知