Borůvka's algorithm
Borůvka's algorithm is a greedy algorithm that computes the minimum spanning tree (MST) of a connected, undirected, weighted graph by iteratively identifying and adding the minimum-weight edges connecting distinct components until all vertices are connected in a single tree.[1]
Developed by Czech mathematician Otakar Borůvka in 1926, the algorithm was originally motivated by the practical problem of optimizing electrical power distribution networks for the West Moravian Power Company, predating the advent of modern computers and representing the first known solution to the MST problem.[2][1]
The algorithm proceeds in phases: it begins with each vertex as its own component, then in each iteration, for every component, selects the minimum-weight outgoing edge to another component, adds these edges, and contracts the components until only one remains; this process guarantees an MST and runs in O(E log V) time, where E is the number of edges and V is the number of vertices.[1]
Though rediscovered independently multiple times—by French mathematician Gustave Choquet in 1938, a Polish team (K. Florek, J. Łukaszewicz, H. Perkal, J. Steinhaus, and S. Zubrzycki) in 1951, and American engineer George Sollin in 1961—Borůvka's original contribution laid foundational groundwork for subsequent MST algorithms like Kruskal's and Prim's, and it remains influential in parallel computing due to its inherent parallelism in selecting edges across components.[2][1]
The algorithm's elegance lies in its simplicity and efficiency for dense graphs, and it has applications beyond electrical grids, including telecommunications network design, clustering in data analysis, and approximating solutions in combinatorial optimization problems.[2]
Overview
Description
Borůvka's algorithm is a greedy algorithm designed to find a minimum spanning tree (MST) of an undirected, connected, weighted graph, or a minimum spanning forest in the case of a disconnected graph.[3][4] The algorithm selects edges in a way that progressively builds the tree by always choosing the lowest-weight options that connect components without forming cycles, ensuring the final structure spans all vertices with minimal total edge weight.[5]
The primary purpose of Borůvka's algorithm is to solve the minimum spanning tree problem, which seeks a subset of edges that connects every vertex in the graph while minimizing the sum of their weights and avoiding cycles.[5] Given an input graph G = (V, E) where V is the set of vertices, E is the set of edges, and each edge e \in E has a weight w(e), the algorithm outputs a tree T \subseteq E (or forest for disconnected graphs) such that the total weight \sum_{e \in T} w(e) is minimized.[4][3]
Key characteristics of the algorithm include its phased operation, where each phase merges connected components by identifying and adding the cheapest outgoing edge from each component to a different one, reducing the number of components by at least half per phase.[4] It is highly parallelizable, as the selection of minimum outgoing edges for different components can occur independently, making it suitable for concurrent implementations.[4] Additionally, the algorithm performs efficiently on dense graphs, where the number of edges is quadratic in the number of vertices, due to its balanced workload across phases.[4]
History
Borůvka's algorithm was first published in 1926 by the Czech mathematician Otakar Borůvka as a solution to the minimum spanning tree problem motivated by the practical need to optimize the electrical power grid in the region of Moravia.[2] Borůvka presented his method in two papers: a mathematical treatment titled "O jistém problému minimálním" (On a certain minimal problem) and an applied version titled "Přispěvek k řešení otázky minimálního obdělání Moravské elektrické sítě" (Contribution to the solution of a problem of minimizing the construction of the Moravian electrical network), aimed at engineers involved in network design.[6] These works established the algorithm as the earliest known approach to constructing a minimum spanning tree in a weighted graph, predating later developments by over three decades.[2]
The algorithm was independently rediscovered multiple times due to its inherent simplicity and applicability across fields like optimization and clustering. In 1938, French mathematician Gustave Choquet described a similar procedure in a note analyzing the minimum spanning tree problem, though without a full proof of correctness; this work was communicated to the Comptes Rendus de l'Académie des Sciences by Élie Cartan.[6] It reemerged in 1951 in the Polish publication "Taxonomia Wrocławska" by Jerzy Florek, Jerzy Łukaszewicz, Józef Perkal, Hugo Steinhaus, and Stanisław Zubrzycki, where it was applied to taxonomic clustering problems in anthropology.[6] In 1961, Georges Sollin independently formulated the method in a manuscript entitled "Problème de l'Arbre Minimum" and presented it at a seminar in Paris organized by Claude Berge.[6]
These repeated independent discoveries underscore the algorithm's intuitive appeal, as it relies on straightforward greedy choices without requiring advanced theoretical machinery.[6] As a result, naming conventions vary: it is commonly known as Borůvka's algorithm in recognition of the original publication, but frequently referred to as Sollin's algorithm in contexts involving parallel algorithms, reflecting Sollin's influence on computational implementations.[7] This predates the more widely recognized algorithms of Joseph Kruskal in 1956 and Robert Prim in 1957, positioning Borůvka's contribution as foundational in the evolution of graph optimization techniques.[6]
Background Concepts
Minimum Spanning Trees
In a connected, undirected graph with distinct edge weights, a minimum spanning tree (MST) is a subset of the edges that forms a tree connecting all vertices, contains no cycles, and has the minimum possible total edge weight among all such spanning trees.[8] This structure ensures full connectivity while minimizing cost, making it a core problem in graph theory.[8]
Key properties of MSTs include uniqueness under certain conditions and optimality criteria based on cuts and cycles. If all edge weights in the graph are distinct, the MST is unique, as any deviation would increase the total weight.[4] The cut property states that for any partition of the vertices into two nonempty sets (a cut), the minimum-weight edge crossing the cut belongs to every MST.[9] Complementing this, the cycle property asserts that for any cycle in the graph, the maximum-weight edge on that cycle cannot belong to any MST, ensuring no redundant high-cost connections.[9]
For disconnected graphs, the analogous structure is a minimum spanning forest, which consists of an MST for each connected component, collectively minimizing the total weight while spanning all vertices without cycles.[10] MSTs hold significant importance in applications such as network design, where they optimize connectivity at minimal cost in telecommunications, electrical grids, or transportation systems.[11] They also underpin clustering techniques, such as forming k clusters by computing an MST and removing the k-1 heaviest edges, and serve as building blocks in approximation algorithms for harder problems like the traveling salesman problem.[12][11]
Graph Theory Prerequisites
An undirected graph G = (V, E) consists of a finite set V of vertices and a set E of edges, where each edge is an unordered pair of distinct vertices from V.[13] In a weighted undirected graph, each edge e \in E is assigned a positive real weight w(e) \in \mathbb{R}^+, often representing costs or distances.[4]
Connected components in an undirected graph partition the vertex set V into maximal subsets where every pair of vertices within a subset is connected by a path (a sequence of adjacent edges), but no path exists between vertices in different subsets.[14] These components form induced subgraphs that are themselves connected and cannot be extended further within G.[14]
Borůvka's algorithm operates on undirected graphs with positive edge weights and accommodates possibly disconnected inputs, producing a minimum spanning forest consisting of minimum spanning trees for each connected component.[4]
Standard notations denote the number of vertices as n = |V| and the number of edges as m = |E|.[15] Graphs are commonly represented using adjacency lists, where each vertex maintains a list of its neighboring vertices (and weights for weighted graphs), or adjacency matrices, an n \times n matrix where entry (i,j) indicates the weight of the edge between vertices i and j (or absence thereof).[16] Adjacency lists are space-efficient for sparse graphs (m \ll n^2), while matrices facilitate quick edge queries.[16]
The Algorithm
Step-by-Step Procedure
Borůvka's algorithm initializes a spanning forest F by treating each vertex of the input graph G = (V, E) as its own singleton component, yielding |V| components in total. This setup represents the starting point of the forest, where no edges have been added yet.[4][17]
The algorithm then enters an iterative phase that continues as long as there is more than one component in the forest. In each such phase, for every current component C, the minimum-weight edge e is identified that has one endpoint in C and the other endpoint in a different component. This search is performed independently for each component, focusing only on outgoing edges to external vertices.[4][17][2]
Once these minimum-weight edges are found for all components, they are simultaneously added to the spanning forest F. The components connected by each such edge are then unioned together, forming larger components. Because every component contributes at least one outgoing edge (and incoming edges pair with them), this merging process reduces the number of components by at least a factor of two per phase, though it may reduce them more substantially if multiple components connect in chains or cycles of merges.[4][17][2]
The iteration repeats with the updated components until only a single component remains, at which point F constitutes the minimum spanning tree of G. If the original graph is disconnected, the process terminates with a minimum spanning forest when no further outgoing edges exist between components. In cases of tied minimum weights, an arbitrary edge among the minima is selected for each component, ensuring the added edges connect distinct components and thus avoid cycles.[4][17][2]
Pseudocode
Borůvka's algorithm can be implemented using a union-find data structure to efficiently track connected components and merge them iteratively. The high-level structure initializes an empty forest F consisting of all vertices and no edges. While the number of components in F exceeds one, for each component, the minimum-weight outgoing edge is selected and added to F, followed by merging the connected components.[18]
The following pseudocode provides a detailed implementation, assuming the graph G = (V, E) is undirected and connected with distinct edge weights for simplicity; it uses an array to track safe (minimum outgoing) edges per component and a union-find subroutine for labeling and merging components.[18]
BORUVKA(V, E)
1 F ← (V, ∅) // Initialize forest with all vertices, no edges
2 count ← ConnectedComponents(F) // Number of components, initially |V|
3 while count > 1
4 AddAllSafeEdges(E, F, count)
5 count ← ConnectedComponents(F)
6 return F
ADDALLSAFEEDGES(E, F, count)
1 for i ← 1 to count
2 safe[i] ← null // No safe edge selected yet for component i
3 for each edge uv ∈ E
4 if comp(u) ≠ comp(v) // u and v in different components
5 if safe[comp(u)] = null or w(uv) < w(safe[comp(u)])
6 safe[comp(u)] ← uv
7 if safe[comp(v)] = null or w(uv) < w(safe[comp(v)])
8 safe[comp(v)] ← uv
9 for i ← 1 to count
10 if safe[i] ≠ null
11 add safe[i] to F // Union the components implicitly via later ConnectedComponents
BORUVKA(V, E)
1 F ← (V, ∅) // Initialize forest with all vertices, no edges
2 count ← ConnectedComponents(F) // Number of components, initially |V|
3 while count > 1
4 AddAllSafeEdges(E, F, count)
5 count ← ConnectedComponents(F)
6 return F
ADDALLSAFEEDGES(E, F, count)
1 for i ← 1 to count
2 safe[i] ← null // No safe edge selected yet for component i
3 for each edge uv ∈ E
4 if comp(u) ≠ comp(v) // u and v in different components
5 if safe[comp(u)] = null or w(uv) < w(safe[comp(u)])
6 safe[comp(u)] ← uv
7 if safe[comp(v)] = null or w(uv) < w(safe[comp(v)])
8 safe[comp(v)] ← uv
9 for i ← 1 to count
10 if safe[i] ≠ null
11 add safe[i] to F // Union the components implicitly via later ConnectedComponents
Here, ConnectedComponents(F) labels each vertex with its component ID (via union-find with path compression and union by rank for efficiency) and returns the number of components; comp(v) returns the label of vertex v. Tie-breaking is handled by selecting the minimum weight edge, with the assumption of distinct weights ensuring uniqueness; if weights are not distinct, an arbitrary minimum can be chosen.[18]
For implementation, the graph is typically represented using adjacency lists to facilitate iteration over edges in O(|E|) time per phase. The union-find structure supports finding and merging components in nearly amortized constant time per operation. To handle disconnected graphs, the algorithm naturally produces a minimum spanning forest by terminating when no further merges are possible, with each component yielding its own spanning tree.[18]
Analysis
Time and Space Complexity
Borůvka's algorithm exhibits a worst-case time complexity of O(m \log n), where n is the number of vertices and m is the number of edges in the input graph. This bound arises from the algorithm's phase-based structure, in which there are at most O(\log n) phases, as each phase reduces the number of connected components by at least half. In each phase, the algorithm identifies the minimum-weight outgoing edge for every component by scanning all edges, which takes O(m) time, and performs unions using a union-find data structure with path compression and union by rank, which operates in nearly linear time overall across all phases.[19]
The space complexity of Borůvka's algorithm is O(n + m), primarily due to the storage required for the graph's adjacency lists or edge list representation and the union-find structure, which uses arrays of size proportional to n.[19]
Optimizations exist that achieve linear time O(m) for restricted graph classes. For planar graphs, a contraction-based variant of Borůvka's algorithm runs in O(m) time by leveraging the graph's bounded degree and separator properties to efficiently manage contractions and edge cleanups per phase.[20] For broader minor-closed graph families (excluding trivial cases like empty or complete graphs), deterministic linear-time MST algorithms build upon Borůvka-style contractions combined with linear-time separators.[21] Additionally, randomized variants, such as the one incorporating Borůvka phases with edge sampling and verification, achieve expected O(m) time for general graphs.
Correctness
The correctness of Borůvka's algorithm relies on the greedy choice property of minimum spanning trees (MSTs), where the algorithm selects safe edges—those that can be included in some MST without compromising optimality—in each phase. Specifically, in every iteration, for each connected component in the current forest, the algorithm identifies the minimum-weight edge leaving that component, which crosses the cut defined by the component and the rest of the graph. By the MST cut property, this edge is safe and belongs to at least one MST of the graph.[4][22]
The proof proceeds by induction on the number of phases. In the base case, the initial forest consists of single-vertex components with no edges, which is trivially a subset of any MST. Assume that after k phases, the current forest F_k is contained in some MST T of the graph. In the (k+1)-th phase, the added edges are safe with respect to F_k, so they can replace any conflicting edges in T while preserving or reducing the total weight, ensuring F_{k+1} remains a subset of some MST. Since each phase connects components without cycles (as edges only link distinct components), the process maintains a forest that grows toward a spanning tree.[20][4]
For disconnected graphs, the algorithm naturally extends to produce a minimum spanning forest (MSF), as it connects components within each connected component of the original graph using the same safe-edge selection, yielding the minimum-weight forest with no cycles.[23]
Cycle avoidance is inherent: edges are only added between different components in the current forest, preventing intra-component connections that would form cycles, consistent with the acyclicity requirement of MSTs.[4][24]
Illustrative Example
Graph Setup
To illustrate Borůvka's algorithm, consider the following connected, undirected, weighted graph with seven vertices labeled A, B, C, D, E, F, and G. The edges and their respective weights are:
- A–B: 1
- A–D: 4
- A–G: 7
- B–C: 2
- B–E: 5
- B–G: 8
- C–D: 3
- C–F: 6
- D–E: 2
- D–G: 5
- E–F: 4
- F–G: 1
This configuration is connected, ensuring the graph has a minimum spanning tree.
Initially, the algorithm treats each vertex as a separate component, resulting in seven singleton sets: {A}, {B}, {C}, {D}, {E}, {F}, {G}.
The graph can be visualized with vertices arranged in a roughly circular layout (A at the top, proceeding clockwise to G), with edges drawn as straight lines labeled by their weights; thicker lines could represent lower weights for emphasis in a diagram.
This example graph is chosen for its simplicity, allowing manual tracing of the algorithm's steps, while its structure necessitates multiple merging phases to fully connect the components, highlighting the iterative contraction process.
Execution Steps
In the first phase of Borůvka's algorithm applied to the example graph, each singleton component selects its minimum-weight outgoing edge:
- {A} selects A–B (1)
- {B} selects B–A (1)
- {C} selects C–B (2)
- {D} selects D–E (2)
- {E} selects E–D (2)
- {F} selects F–G (1)
- {G} selects G–F (1)
The unique selected edges added to the MST are A–B (1), B–C (2), D–E (2), and F–G (1). These cause merges into three components: {A, B, C}, {D, E}, and {F, G}.
In the second phase, the three components each select their minimum-weight outgoing edge to another component:
- {A, B, C} selects C–D (3) to {D, E}
- {D, E} selects D–C (3) to {A, B, C}
- {F, G} selects F–E (4) to {D, E}
Adding C–D (3) and E–F (4) merges all into one component: {A, B, C, D, E, F, G}, completing the MST.
The total weight of the MST is 13, formed by the edges A–B (1), B–C (2), C–D (3), D–E (2), E–F (4), and F–G (1).
Comparisons and Variants
Comparison with Other MST Algorithms
Borůvka's algorithm shares the greedy nature of Kruskal's algorithm, as both construct the minimum spanning tree (MST) by repeatedly selecting the lightest edges that connect disjoint components without forming cycles. However, while Kruskal's algorithm requires sorting all edges globally in ascending order before processing them sequentially, Borůvka's algorithm avoids this by identifying the minimum-weight edge incident to each component locally in each phase, which eliminates the need for a full edge sort upfront.[25] Both algorithms achieve the same asymptotic time complexity of O(m \log n), where m is the number of edges and n is the number of vertices, but Borůvka's phase-based structure makes it more amenable to parallelization, as the minimum edges for different components can be found concurrently.[26]
In contrast to Prim's algorithm, which grows a single MST starting from an arbitrary vertex by iteratively adding the minimum-weight edge connecting the growing tree to an unvisited vertex, Borůvka's algorithm simultaneously expands multiple trees—one per component—by selecting the cheapest outgoing edge from each. This multi-source growth leads to faster initial contraction of components compared to Prim's single-focus approach, particularly in distributed or parallel environments.[25] Prim's algorithm, especially when implemented with Fibonacci heaps, performs well on dense graphs with O(m + n \log n) time, making it preferable for scenarios where edge density is high and sequential efficiency is prioritized over parallelism.[26]
A key strength of Borůvka's algorithm lies in its simplicity and inherent parallelism, requiring no global data structures like priority queues for all edges, which reduces overhead in multi-processor settings and allows for efficient implementation on modern hardware such as GPUs.[26] However, it can suffer in graphs with skewed degree distributions, where the number of phases may approach \log n without halving components evenly, and repeated graph contractions can become computationally expensive if edge counts do not decrease proportionally.[25] Borůvka's is particularly advantageous in parallel computing contexts, such as distributed systems, whereas Kruskal's excels in sparse graphs due to its straightforward union-find integration, and Prim's suits dense, sequential applications like network design.[27]
Parallel and Modern Variants
Borůvka's algorithm, also referred to as Sollin's algorithm in parallel contexts, lends itself naturally to parallelization because each phase involves independent computations across connected components, where vertices within a component simultaneously identify their minimum-weight outgoing edge. This structure allows for efficient distribution of the minimum-edge finding step across multiple processors, with merging of components handled in subsequent parallel reductions. Implementations on shared-memory systems demonstrate significant speedups for sparse graphs, scaling to hundreds of threads with speedups up to 30x while maintaining low synchronization overhead. In distributed systems, such as those modeling large-scale networks, the algorithm's phases facilitate message-passing paradigms where components exchange minimal edge information asynchronously, enabling fault-tolerant computations in environments like MapReduce.[28][29]
Modern variants build on Borůvka's iterative contraction framework to achieve near-linear time complexities. The randomized algorithm by Karger, Klein, and Tarjan integrates Borůvka phases with edge sampling: in each phase, a random subset of edges is contracted if they form cycles, reducing the graph size exponentially with high probability, yielding an expected O(m) runtime for dense graphs. This approach avoids explicit priority queues by leveraging sampling to bound the number of phases to O(log n). For a deterministic alternative, Chazelle's algorithm employs soft heaps—an approximate priority queue permitting controlled errors—to simulate Borůvka steps within a linking framework, achieving O(m α(m, n)) time, where α is the inverse Ackermann function, nearly optimal for practical graph sizes. The soft heap's meld and extract-min operations support efficient edge linking while correcting errors lazily.[30][31]
Beyond theoretical efficiency, Borůvka's variants find applications in network design, where minimum spanning trees minimize connectivity costs, such as in telecommunications infrastructure to optimize cable layouts or in electrical grids for efficient power distribution. In machine learning, the algorithm supports hierarchical clustering by constructing MSTs on similarity graphs, enabling scalable affinity-based methods that reveal data groupings without predefined cluster counts, as seen in large-scale datasets for community detection. For VLSI design, parallel Borůvka implementations optimize power and clock networks by computing low-weight spanning trees amid dense routing constraints, reducing wire lengths and energy consumption in chip layouts. These uses highlight the algorithm's scalability for big data graphs, where parallel phases handle billions of edges in distributed environments.[32][33][34]
Post-2000 developments emphasize hardware acceleration and streaming adaptability. GPU implementations exploit the algorithm's parallelism by assigning components to thousands of threads for simultaneous minimum-edge searches, achieving up to 50x speedups on graphs with up to 5 million vertices compared to CPU baselines, particularly for Euclidean MSTs in geometric data. For approximate MST in massively parallel computation models, where edges are processed in rounds with limited memory per machine, Borůvka-inspired variants use batched contractions and sampling to maintain (1+ε)-approximations with O(n^δ) space per machine, supporting applications like dynamic network analysis.[35][36]