Boruvka 算法:构建最小生成树的贪心策略

在此前的讨论中,我们已经涉及了关于最小生成树的以下几个主题:

在本文中,我们将探讨 Boruvka 算法。与 Prim 算法和 Kruskal 算法一样,Boruvka 算法也是一种贪心算法。下面是该算法的完整步骤。

1) 输入是一个连通的、带权的无向图。
2) 初始化所有顶点,将每个顶点视为一个单独的分量(或集合)。
3) 将最小生成树(MST)初始化为空。
4) 只要存在多于一个的分量,就对每个分量执行以下操作:
   a) 找到一条权值最小的边,该边将此分量连接到任意其他分量。
   b) 如果这条最近的边尚未添加,则将其加入 MST。
5) 返回 MST。

以下是上述算法背后的核心思想(这与 Prim 最小生成树算法 的思想是一致的)。

生成树意味着所有顶点必须是连通的。因此,必须将上述提到的两个不相交的顶点子集连接起来,才能形成一个生成树。并且,它们必须通过权值最小的边相连,这样才能构成最小生成树。

让我们通过下面的例子来理解这个算法。

!Boruvka‘s algorithm Image 1

最初,MST 为空。每个顶点都是一个单独的分量,在下图中以蓝色高亮显示。

!Boruvka‘s algorithm Image 2

对于每个分量,找到将其连接到其他某个分量的最廉价的边。

**分量                        连接到其他分量的最廉价边**
  {0}                           0-1
  {1}                           0-1
  {2}                           2-8
  {3}                           2-3
  {4}                           3-4
  {5}                           5-6
  {6}                           6-7
  {7}                           6-7
  {8}                           2-8

最廉价的边以绿色高亮显示。此时 MST 变为 {0-1, 2-8, 2-3, 3-4, 5-6, 6-7}。

!Boruvka‘s algorithm Image 3

经过上述步骤后,分量为 {{0,1}, {2,3,4,8}, {5,6,7}}。这些分量用蓝色圆圈圈出。

!Boruvka‘s algorithm Image 4

我们再次重复该步骤,即对于每个分量,找到将其连接到其他某个分量的最廉价的边。

**分量                        连接到其他分量的最廉价边**
  {0,1}                        1-2 (或 0-7)
  {2,3,4,8}                    2-5
  {5,6,7}                      2-5

最廉价的边以绿色高亮显示。现在 MST 变为 {0-1, 2-8, 2-3, 3-4, 5-6, 6-7, 1-2, 2-5}

!Boruvka‘s algorithm Image 5

在此阶段,只剩下一个分量 {0, 1, 2, 3, 4, 5, 6, 7, 8},它包含了所有边。由于只剩下一个分量,我们停止并返回 MST。

实现:

以下是上述算法的实现。输入图表示为边的集合,并使用并查集数据结构来跟踪分量。

C++

“`

// Boruvka‘s algorithm to find Minimum Spanning

// Tree of a given connected, undirected and weighted graph

#include

using namespace std;

// Class to represent a graph

class Graph {

int V; // No. of vertices

vector<vector >graph; // default dictionary to store graph

// A utility function to find set of an element i

// (uses path compression technique)

int find(vector& parent, int i)

{

if (parent[i] == i) {

return i;

}

return find(parent, parent[i]);

}

// A function that does union of two sets of x and y

// (uses union by rank)

void unionSet(vector& parent, vector& rank,

int x, int y)

{

int xroot = find(parent, x);

int yroot = find(parent, y);

// Attach smaller rank tree under root of high rank

// tree (Union by Rank)

if (rank[xroot] < rank[yroot]) {

parent[xroot] = yroot;

}

else if (rank[xroot] > rank[yroot]) {

parent[yroot] = xroot;

}

// If ranks are same, then make one as root and

// increment its rank by one

else {

parent[yroot] = xr

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/20435.html
点赞
0.00 平均评分 (0% 分数) - 0