23 Minimum Spanning Trees

Minimum Spanning Trees (MSTs) and Minimum Cost Spanning Trees (MCSTs)
• What is a Minimum Spanning Tree?
• Constructing Minimum Spanning Trees.
• What is a Minimum-Cost Spanning Tree (MCST) ?
• Applications of Minimum Cost Spanning Trees.
• MCST Algorithms:
– Kruskal’s Algorithm.
• Tracing Kruskal’s Algorithm
• Implementation.
– Prim’s algorithm.
• Tracing Prim’s Algorithm
• Implementation.
• Review Questions.
1
What is a Minimum Spanning Tree?
• Let G = (V, E) be a simple, connected, undirected graph that is not
edge-weighted.
• A spanning tree of G is a free tree (i.e., a tree with no root) with | V | - 1
edges that connects all the vertices of the graph.
• Thus a minimum spanning tree T = (V’, E’) for G is a subgraph of G
with the following properties:
 V’ = V
 T is connected
 T is acyclic (  |E’| = |V| - 1)
• A spanning tree is called a tree because every acyclic undirected
graph can be viewed as a general, unordered tree. Because the edges
are undirected, any vertex may be chosen to serve as the root of the
tree.
2
Constructing Minimum Spanning Trees
• Any traversal of a connected, undirected graph
visits all the vertices in that graph. The set of
edges which are traversed during a traversal
forms a spanning tree.
(a) Graph G
• For example, Fig (b) shows a spanning tree of G
obtained from a breadth-first traversal starting at
vertex a.
• Similarly, Fig (c) shows a spanning tree of G
obtained from a depth-first traversal starting at
vertex c.
(b) Breadth-first
spanning tree of G
starting from a
(c) Depth-first
spanning tree of G
starting from c
3
What is a Minimum-Cost Spanning Tree?
• For an edge-weighted , connected, undirected graph, G, the total
cost of G is the sum of the weights on all its edges.
• A minimum-cost spanning tree for G is a minimum spanning tree of
G that has the least total cost.
• Example: The graph
Has 16 spanning trees. Some are:
The graph has two minimum-cost spanning trees, each with a cost of 6:
4
Applications of Minimum-Cost Spanning Trees
Minimum-cost spanning trees have many applications. Some are:
• Building cable networks that join n locations with minimum cost.
• Building a road network that joins n cities with minimum cost.
• Obtaining an independent set of circuit equations for an electrical
network.
• In pattern recognition minimal spanning trees can be used to find noisy
pixels.
5
MCST Algorithms: Kruskal's Algorithm
Kruskal’s algorithm finds the minimum cost spanning
tree of a graph by adding edges one-by-one to an initially empty free
tree
enqueue edges of G in a queue in increasing order of cost.
T=;
while(queue is not empty){
dequeue an edge e;
if(e does not create a cycle with edges in T)
add e to T;
}
return T;
Running time is O(E log V)
6
Tracing Kruskal’s Algorithm
Trace Kruskal's algorithm in finding a minimum-cost spanning tree for the
undirected, weighted graph given below:
The minimum cost is: 24
7
Implementation of Kruskal's Algorithm
public static Graph kruskalsAlgorithm(Graph g){
Graph result = new GraphAsLists(false);
Iterator it = g.getVertices();
while (it.hasNext()){
Vertex v = (Vertex)it.next();
result.addVertex(v.getLabel());
}
PriorityQueue queue = new BinaryHeap(g.getNumberOfEdges());
it = g.getEdges();
while(it.hasNext()){
Edge e = (Edge) it.next();
if (e.getWeight()==null)
throw new IllegalArgumentException("Graph is not weighted");
queue.enqueue(e);
}
while (!queue.isEmpty()){ // test if there is a path from vertex
// from to vertex to before adding the edge
Edge e = (Edge) queue.dequeueMin();
String from = e.getFromVertex().getLabel();
String to = e.getToVertex().getLabel();
if (!result.isReachable(from, to))
adds an edge only, if it
result.addEdge(from,to,e.getWeight());
}
return result;
}
does not create a cycle
8
Implementation of Kruskal's Algorithm (Cont’d)
public abstract class AbstractGraph implements Graph {
public boolean isReachable(String from, String to){
Vertex fromVertex = getVertex(from);
Vertex toVertex = getVertex(to);
if (fromVertex == null || toVertex==null)
throw new IllegalArgumentException("Vertex not in the graph");
PathVisitor visitor = new PathVisitor(toVertex);
this.preorderDepthFirstTraversal(visitor, fromVertex);
return visitor.isReached();
}
private class PathVisitor implements Visitor {
boolean reached = false;
Vertex target;
PathVisitor(Vertex t){target = t;}
public void visit(Object obj){
Vertex v = (Vertex) obj;
if (v.equals(target)) reached = true;
}
public boolean isDone(){return reached;}
boolean isReached(){return reached;}
}
}
9
MCST Algorithms: Prim’s Algorithm
The algorithm continuously increases the size of a tree starting with a
single vertex until it spans all the vertices of G:
Consider a weighted, connected, undirected graph G=(V, E) and a free tree
T = (VT, ET) that is a subgraph of G
Initialize: VT = {x};
// where x is an arbitrary vertex from V
Initialize: ET = ;
repeat{
Choose an edge (v,w) with minimal weight such that v is in VT and w is not
(if there are multiple edges with the same weight, choose arbitrarily but
consistently); // add an minimal weight edge that will not form a cycle
Add vertex v to VT;
add edge (v, w) to ET;
}until (VT == V);
Time Complexity of Prim’s Algorithm:
Graph and Minimum edge weight data structure
Time complexity (total)
adjacency matrix and array
O(V2)
adjacency list and binary heap
O((V + E) log(V)) = O(E log(V))
Adjacency list and Fibonacci heap
O(E + V log(V))
10
Tracing Prim’s Algorithm (Example adopted from Wikipedia)
We want to find a Minimum Cost Spanning Tree for the
graph on the left. The numbers near the edges indicate the
edge weights.
Vertex D has been arbitrarily chosen as a starting point.
Vertices A, B, E and F are connected to D through a single
edge. A is the vertex nearest to D and will be chosen as the
second vertex along with the edge AD.
The next vertex chosen is the vertex nearest to either D or
A. B is 9 away from D and 7 away from A, E is 15, and F is
6. F is the smallest distance away, so we highlight the vertex
F and the arc DF.
11
Tracing Prim’s Algorithm (Cont’d)
The algorithm carries on as above. Vertex B, which is 7
away from A, is highlighted.
In this case, we can choose between C, E, and G. C is 8
away from B, E is 7 away from B, and G is 11 away from F.
E is nearest, so we highlight the vertex E and the arc BE.
Here, the only vertices available are C and G. C is 5 away
from E, and G is 9 away from E. C is chosen, so it is
highlighted along with the arc EC.
12
Tracing Prim’s Algorithm (Cont’d)
Vertex G is the only remaining vertex. It is 11 away from F,
and 9 away from E. E is nearer, so we highlight it and the
arc EG.
Now all the vertices have been selected and the minimum
cost spanning tree is shown in green. In this case, it has
weight 39.
13
Tracing Prim’s Algorithm: An alternative method
Trace Prim’s algorithm starting at vertex a:
Note: Current Active vertex is vertex in the row with minimum weight from the
previous column, v1 is the active vertex in the column where weight appears for the
first time
The resulting minimum-cost spanning tree is:
14
Implementation of Prim’s Algorithm using MinHeap
•
The implementation of Prim's algorithm uses an Entry class, which
contains the following three fields:
– know: a boolean variable indicating whether the weight of the edge from this
vertex to an active vertex v1 is known, initially false for all vertices.
– weight : the minimum known weight from this vertex to an active vertex v1,
initially infinity for all vertices except that of the starting vertex which is 0.
– predecessor : the predecessor of an active vertex v1 in the MCST, initially
unknown for all vertices.
public class Algorithms{
static final class Entry{
boolean known;
int weight;
Vertex predecessor;
Entry(){
known = false;
weight = Integer.MAX_VALUE;
predecessor = null;
}
}
15
Implementation of Prim’s Algorithm using MinHeap (Cont’d)
The idea is to use a table array to remember, for each vertex, the smallest edge
connecting T with that vertex. Each entry in table represents a vertex x. The
object stored at table entry index(x) will have the predecessor of x and the
corresponding edge weight.
make a table of values (known, weight(edge), predecessor) initially
(FALSE,,null) for each vertex except the start vertex table entry is set to
(FALSE, 0, null) ;
MinHeap = ;
MinHeap.enqueue( Association (0, startVertex));
// let tree T be empty;
while (MinHeap is not empty) {
// T has fewer than n vertices
dequeue an Association (weight(e), v) from the MinHeap;
Update table entry for v to (TRUE, weight(e), v); // add v and e to T
for( each emanating edge f = (v, u) of v){
if( table[u].known == FALSE ) // u is not already in T
if (weight(f) < table[u].weight) { // find the current min edge weight
table[u].weight = weight(f);
table[u].predecessor = v;
enqueue(Association(weight(f), u);
}
}
}
}
16
Implementation of Prim’s Algorithm using MinHeap (Cont’d)
Prim’s algorithm can be implemented as shown below:
public static Graph primsAlgorithm(Graph g, Vertex start){
int n = g.getNumberOfVertices();
Entry table[] = new Entry[n];
for(int v = 0; v < n; v++)
table[v] = new Entry();
table[g.getIndex(start)].weight = 0;
PriorityQueue queue = new BinaryHeap(g.getNumberOfEdges());
queue.enqueue(new Association(new Integer(0), start));
while(!queue.isEmpty()) {
Association association = (Association)queue.dequeueMin();
Vertex v1 = (Vertex) association.getValue();
int n1 = g.getIndex(v1);
if(!table[n1].known){
table[n1].known = true;
Iterator p = v1.getEmanatingEdges();
while (p.hasNext()){
Edge edge = (Edge) p.next();
Vertex v2 = edge.getMate(v1);
int n2 = g.getIndex(v2);
Integer weight = (Integer) edge.getWeight();
int d = weight.intValue();
17
Implementation of Prim’s Algorithm using MinHeap (Cont'd)
if(!table[n2].known && d < table[n2].weight){
table[n2].weight = d; table[n2].predecessor = v1;
queue.enqueue(new Association(new Integer(d), v2));
}
}
}
}
GraphAsLists result = new GraphAsLists(false);
Iterator it = g.getVertices(); //add vertices of this graph to result
while (it.hasNext()){
Vertex v = (Vertex) it.next();
result.addVertex(v.getLabel());
}
// add edges to result using each vertex predecessor in table
it = g.getVertices();
while (it.hasNext()){// Vertex v = (Vertex) it.next();
if (v != start){
int index = g.getIndex(v);
String from = v.getLabel();
String to = table[index].predecessor.getLabel();
result.addEdge(from, to, new Integer(table[index].distance));
}
}
return result;
}
18
Tracing Prim’s Algorithm from the MinHeap implementation
Trace Prim’s algorithm in finding a MCST starting from vertex A:
B
30
20
12
C
6
C
2
D
3
E
4
queue
front
rear
E
F
0
null
6
9
B
1
table
5
2
A
A
0
D
A
0
F

null
B
1
F

null
C
2
D
3
F

null
0
A
F

null
E
4
queue
front
rear
table
T
0
null
A
0
F
30
A
B
1
F
2
A
C
2
D
3
F
9
A
F

null
E
4
2
C
9
D
30
B
Enqueue edge
weights for
edges
emanating from
A
queue
front
rear
table
T
0
null
F
5
C
T
2
A
F
6
C
F
6
C
5
B
6
D
6
E
9
D
30
B
Enqueue edge weights for
edges emanating from C
19
Tracing Prim’s Algorithm from the MinHeap implementation (Cont’d)
B
A
0
20
30
5
A
6
C
D
3
E
4
queue
front
rear
E
6
9
C
2
table
12
2
B
1
T
5
C
T
0
null
D
A
0
B
1
T
2
A
C
2
D
3
F
6
C
6
D
F
6
C
E
4
6
E
9
D
front
30
B
queue
rear
queue
rear
table
T
0
null
T
5
C
A
0
The MCST:
B
1
T
6
C
T
2
A
C
2
D
3
F
6
C
E
4
6
E
front
9
D
30
B
table
B
5
A
2
C
6
E
T
0
null
T
5
C
T
2
A
T
6
C
T
6
C
6
D
20
Note on MCSTs generated by Prim’s and Kruskal’s Algorithms
Note: It is not necessary that Prim's and Kruskal's algorithm generate the same minimum-cost
spanning tree.
For example for the graph:
Kruskal's algorithm (that imposes an ordering on edges with equal weights) results
in the following minimum cost spanning tree:
The same tree is generated by Prim's algorithm if the start vertex is any of: A, B, or
D; however if the start vertex is C the minimum cost spanning tree is:
21
Review Questions
GB
1. Find the breadth-first spanning tree and depth-first spanning
tree of the graph GA shown above.
2. For the graph GB shown above, trace the execution of Prim's
algorithm as it finds the minimum-cost spanning tree of the
graph starting from vertex a.
3. Repeat question 2 above using Kruskal's algorithm.
22