Bor?vka 算法求 MST 最小生成树

基本思路:用定点数组记录每个子树的最近邻居。对于每一条边进行处理:如果这条边连成的两个顶点同属于一个集合,则不处理,否则检测这条边连接的两个子树,如果是连接这两个子树的最小边,则更新 (合并)。时间复杂度平均 \(O(V+E)\),最坏 \(O((V+E)\log V)\)。

下面是 Bor?vka 算法演示动图:(源:Wikimedia)

程序代码:

struct node {int x, y, w; } edge[M];
int d[N];   // 各子树的最小连外边的权值
int e[N];   // 各子树的最小连外边的索引
bool v[M];  // 防止边重复统计

int fa[N];
int find(int x) {return x==fa[x] ? x : (fa[x]=find(fa[x])); }
void join(int x, int y) {fa[find(x)]=find(y); }

int Boruvka() {
    int tot=0;
    for (int i=1; i<=n; ++i) fa[i]=i;
    while (true) {
        int cur=0;
        for (int i=1; i<=n; ++i) d[i]=inf;
        for (int i=1; i<=m; ++i) {
            int a=find(edge[i].x), b=find(edge[i].y), c=edge[i].w;
            if (a==b) continue;
            cur++;
            if (c<d[a] || c==d[a] && i<e[a]) d[a]=c, e[a]=i;
            if (c<d[b] || c==d[b] && i<e[b]) d[b]=c, e[b]=i;
        }
        if (cur==0) break;
        for (int i=1; i<=n; ++i) if (d[i]!=inf && !v[e[i]]) {
            join(edge[e[i]].x, edge[e[i]].y), tot+=edge[e[i]].w;
            v[e[i]]=true;
        }
    }
    return tot;
}

原文地址:https://www.cnblogs.com/greyqz/p/9536352.html

时间: 2024-08-29 23:02:56

Bor?vka 算法求 MST 最小生成树的相关文章

Codeforces.888G.Xor-MST(Bor?vka算法求MST 贪心 Trie)

题目链接 \(Description\) 有一张\(n\)个点的完全图,每个点的权值为\(a_i\),两个点之间的边权为\(a_i\ xor\ a_j\).求该图的最小生成树. \(n\leq2*10^5,0\leq ai<2^{30}\). \(Solution\) 代码好神啊. 依旧是从高到低考虑每一位.对于当前位i,如果所有点在这一位都为0或1,不需要管(任何边在这一位都为0). 否则可以把点分为两个集合,即i位为0和1的集合,这两个集合间必须存在一条边,且边权这一位只能为1. 考虑怎么高

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 1068

【BZOJ1937】[Shoi2004]Mst 最小生成树 KM算法(线性规划)

[BZOJ1937][Shoi2004]Mst 最小生成树 Description Input 第一行为N.M,其中 表示顶点的数目, 表示边的数目.顶点的编号为1.2.3.…….N-1.N.接下来的M行,每行三个整数Ui,Vi,Wi,表示顶点Ui与Vi之间有一条边,其权值为Wi.所有的边在输入中会且仅会出现一次.再接着N-1行,每行两个整数Xi.Yi,表示顶点Xi与Yi之间的边是T的一条边. Output 输出最小权值 Sample Input 6 9 1 2 2 1 3 2 2 3 3 3

[BZOJ1937][SHOI2004]Mst最小生成树(KM算法,最大费用流)

1937: [Shoi2004]Mst 最小生成树 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 802  Solved: 344[Submit][Status][Discuss] Description Input 第 一行为N.M,其中 表示顶点的数目, 表示边的数目.顶点的编号为1.2.3.…….N-1.N.接下来的M行,每行三个整数Ui,Vi,Wi,表示顶点Ui与Vi之间有一条边,其权值为 Wi.所有的边在输入中会且仅会出现一次.再接着N-1

Prime算法求最小生成树 (邻接表)

/* Name: Prime算法求最小生成树 (邻接表) Copyright: Author: 巧若拙 Date: 25/11/14 13:38 Description: 实现了 Prime算法求最小生成树 (邻接表)的普通算法和最小堆优化算法. */ #include<stdio.h> #include<stdlib.h> #define MAX 2000   //最大顶点数量 #define INFINITY 999999   //无穷大 typedef int VertexT

Prime算法求最小生成树 (邻接矩阵)

/* Name: Prime算法求最小生成树 (邻接矩阵) Copyright: Author: 巧若拙 Date: 25/11/14 13:38 Description: 实现了 Prime算法求最小生成树 (邻接矩阵)的普通算法和最小堆优化算法. */ #include<stdio.h> #include<stdlib.h> #define MAX 2000   //最大顶点数量 #define INFINITY 999999   //无穷大 typedef struct Mi

利用Kruskal算法求最小生成树解决聪明的猴子问题 -- 数据结构

题目:聪明的猴子 链接:https://ac.nowcoder.com/acm/problem/19964 在一个热带雨林中生存着一群猴子,它们以树上的果子为生.昨天下了一场大雨,现在雨过天晴,但整个雨林的地 表还是被大水淹没着,部分植物的树冠露在水面上.猴子不会游泳,但跳跃能力比较强,它们仍然可以在露出水面 的不同树冠上来回穿梭,以找到喜欢吃的果实.现在,在这个地区露出水面的有N棵树,假设每棵树本身的直径都 很小,可以忽略不计.我们在这块区域上建立直角坐标系,则每一棵树的位置由其所对应的坐标表

算法8-6:最小生成树研究现状

目前已经介绍了Kruskal和Prim算法,他们的复杂度一个是E logE一个是E logV,那么有没有复杂度为E的算法呢?理论上是可能的,但是目前还没有发现该算法.下图是最小生成树算法的发展过程. 从图中可以看到复杂度越來越接近E. 最小生成树的应用 欧几里德最小生成树 问题描述:给定一系列点的坐标,求包含所有点的最小生成树. 下图是这个问题的一个例子. 解决这个问题的基本思想就是先将每个点都看成一个独立的cluster,每次合并一对距离最近的cluster,直到所有的点都合并在一起为止.这种

poj 1679 The Unique MST 最小生成树

点击打开链接 http://poj.org/problem?id=1679 题意:给一个无向图,问最小生成树是否唯一,如果唯一就输出最小生成树的所有边的权值的和,如果不唯一,那么就输出Not Unique! 思路:在用prime算法求最小生成树的过程中,在找到权值最小的一个节点之后,先判断一下,这个节点的权值是否可以由好几条路径求得,并且权值都等于当前权值,如果是的话,那么最小生成树就不唯一.那么如何判断呢?可以用一个flag数组标记,0代表这个点得到当前权值的路径唯一,1代表不唯一,初始化全为