Minimum spanning trees
Consider a connected, undirected, and edge-weighted graph
Example
Consider the graph shown below.

The highlighted edges in the two graphs below show two spanning trees for the graph above. The first one has weight 31 and is not minimum. The second one is a minimum spanning tree with weight 30.


As an application example, if the graph models an electronic circuit board so that
the vertices are the components and
the edges are the possible routes for the power/clock wires between the components,
then a minimum spanning tree of the graph gives a way to connect all the components with the power/clock wire by using the minimum amount of wire.
Note that we only consider connected graphs: for graphs with many components, we could compute a minimum spanning trees for each component individually. And we only consider edge-weighted undirected graphs; for directed graphs the analog concept is called “spanning arborescence of minimum weight” or “optimal branching”, see, for instance, the Wikipedia page on Edmond’s algorithm. These are not included in the course.
A generic greedy approach
Given a graph, it may have an exponential amount of spanning trees. Thus enumerating over all of them in order to find a minimum one is not a feasible solution. But there are very fast algorithms solving the problem:
Kruskal’s algorithm
Prim’s algorithm
Both are greedy algorithms (recall Section Greedy Algorithms).
They build an MST by starting from an empty set and
then adding edges greedily one-by-one until the edge set is a tree spanning
the whole graph.
During the construction of this edge set, call it
Before each iteration of the main loop,
is a subset of some MST.
To maintain the invariant,
the algorithms then select and add
a safe edge for
We now only need a way to efficiently detect safe edges. For that, we use the following definitions:
A cut for a graph
is a partition of . An edge crosses a cut
if its other endpoint is in and other in . An edge is a light edge crossing a cut if its weight is the smallest among those edges that cross the cut.
Example
Consider the graph below.
The cut

The following theorem gives an easy method for the greedy algorithms
to select the next safe edge to be included in the MST under construction.
Essentially, it says that for any cut that doesn’t split the partial MST
under construction, one can choose any crossing edge with the smallest weight
to be included in the MST.
We need one more definition: a cut
Theorem
Let
Example
Again, consider the graph below.
The cut

The light edges crossing the cut are
Proof: (Sketch)
Let
If
Suppose that
Kruskal’s algorithm
Kruskal’s algorithm finds the next safe edge to be added by
first sorting the edges in non-decreasing order by their weight, and
then finding the smallest-weight edge that connects two trees in the current edge set
.
To quickly detect whether an edge connects two trees,
the vertices in the trees are maintained in a disjoint-sets data structure
(recall Section Disjoint-sets with the union-find data structure).
When an edge is added, the trees in question merge into a new larger tree.
The cut is not explicitly maintained but for an edge
In pseudo-code:
With the rank-based disjoint-sets implementation introduced in
Section Disjoint-sets with the union-find data structure,
one can argue that the worst-case running time of
the algorithm is
Example: Applying Kruskal’s algorithm
Consider the graph shown below.
The edges in a weight-sorted order are (edges with the same weight are ordered arbitrarily):

First, we add the edge

Next, we add the edge

Next, we add the edge

The next edge

Next, we add the edge

The next edges

The result shown above is an MST of weight 30.
Prim’s algorithm
Prim’s algorithm also implements the generic greedy MST finding algorithm but selects the next safe edge in a different way. It maintains the cut explicitly:
on the other half is the whole MST constructed so far, while
the other half are the vertices not yet joined to the MST.
The process starts from an arbitrary root vertex.
Then, at each step,
an arbitrary light edge from the first half to the second half is selected and
thus one vertex is moved from the second half to the first.
To select a light edge quickly, each vertex in the second half
maintains, as attributes,
the weight (referred to as “key” in the pseudo-code) and
the other end of a smallest weight edge (“parent” in the pseudo-code)
coming to it from the first half.
All the vertices in the second half are stored in a minimum priority queue
In pseudo-code:
Example: Applying Prim’s algorithm
Consider again the graph shown below.

The graphs below show the constructed spanning tree
(the highlighted edges) at the end of each while-loop execution,
green vertices are the ones not in

Next, the vertex

Now the edge

Next, add the edge

Next, add the adage

Next, add the age

Next, add the age

The final result is an MST of wight 30.
Let’s perform a worst-case running time analysis of the algorithm. Assume that priority queues are are implemented with heaps (recall Section Priority queues with binary heaps).
The initialization phase, including the priority queue initialization, can be done in
. It is quite easy to see that in this case it is easy to initialize the priority queue in linear time as well and thus the initialization phase can in fact be done in time . The
while
-loop executes times as one vertex is removed from in each iteration. Removing a smallest element from the priority queue takes time
The set
can be implemented as a linked list or an array of elements and thus adding an edge to it takes constant time.
Each edge is considered twice, once for each end point
The keys of the vertices are thus updates at most
times, each update taking time.
The total running time is thus
as
A small side track: Steiner trees
As shown above, we have very efficient algorithms for finding minimum spanning trees. But if we make a rather small modification in the problem definition, we obtain a problem for which we do not know any polynomial time algorithms at the moment. In fact, many believe (but we cannot yet prove this) that such algorithms do not exist. Consider the problem of finding minimum Steiner trees instead of minimum spanning trees.
Definition: Minimum Steiner tree problem
Given a connected, edge-weighted undirected graph
That is, the tree does not have to span all the vertices but only the terminals and some of the other needed to connect the terminals to each other.
Example
Consider the graph on the left below with the terminal vertices

The following is a Steiner tree of weight 15.

The graph below shows, in order to illustrate the difference in the problem definition, a minimum spanning tree for the graph.

As an application example, we could extend our earlier circuit board example. Now
the terminal vertices are the components,
the other vertices are crossing positions on the board through which we can draw the power/clock wires, and
the edges are the possible connections between the components and crossings.
We now want to find a minimum Steiner tree instead of a minimum spanning tree as we do not need to connect power/clock wire to each of the crossings, only the components need to be connected to each other.
Finding minimum Steiner trees is one example of an NP-hard problem.
For such problems, we do not know algorithms
that would have polynomial worst-case running time.
There are algorithms that solve the minimum Steiner tree
problem in time that is (i) exponential in the size of the terminal set