Lecture 26: Minimum Spanning Trees
- MST, Cut Property, Generic MST Algorithm
- Prim’s Algorithm
- Kruskal’s Algorithm
Spanning Trees
MST vs. SPT
A shortest paths tree depends on the start vertex:
- Because it tells you how to get from a source (起始点)to EVERYTHING.
There is no source for a MST.
Nonetheless, the MST sometimes happens to be an SPT for a specific vertex.
Exampel:
A Useful Tool for Finding the MST: Cut Property
- A cut is an assignment of a graph’s nodes to two non-empty sets.
- A crossing edge is an edge which connects a node from one set to a node from the other set.
Cut property: Given any cut, minimum weight crossing edge is in the MST.
- For rest of today, we’ll assume edge weights are unique.
Cut Property in Action
Cut Property Proof
Generic MST Finding Algorithm
Start with no edges in the MST.
- Find a cut that has no crossing edges in the MST.
- Add smallest crossing edge to the MST.
- Repeat until V-1 edges.
This should work, but we need some way of finding a cut with no crossing edges!
Random isn’t a very good idea.
Prim’s Algorithm
Prim’s Algorithm
Start from some arbitrary start node.
- Repeatedly add shortest edge (mark black) that has one node inside the MST under construction.
- Repeat until V-1 edges.
Conceptual Prim’s Algorithm Demo (Link)
Why does Prim’s work?
Special case of generic algorithm.
- Suppose we add edge e = v->w.
- Side 1 of cut is all vertices connected to start, side 2 is all the others.
- No crossing edge is black (all connected edges on side 1).
- No crossing edge has lower weight (consider in increasing order).
Prim’s Algorithm Implementation
The natural implementation of the conceptual version of Prim’s algorithm is highly inefficient.
- Example: Iterating over purple edges shown is unnecessary and slow.
Can use some cleverness and a PQ to speed things up.
Realistic Implementation Demo (Link)
- Very similar to Dijkstra’s!
Prim’s vs. Dijkstra’s
Prim’s and Dijkstra’s algorithms are exactly the same, except Dijkstra’s considers “distance from the source”, and Prim’s considers “distance from the tree.”
Visit order:
- Dijkstra’s algorithm visits vertices in order of distance from the source.
- Prim’s algorithm visits vertices in order of distance from the MST under construction.
Relaxation:
- Relaxation in Dijkstra’s considers an edge better based on distance to source.
- Relaxation in Prim’s considers an edge better based on distance to tree.
public class PrimMST {
public PrimMST(EdgeWeightedGraph G) {
edgeTo = new Edge[G.V()];
distTo = new double[G.V()];
marked = new boolean[G.V()];
fringe = new SpecialPQ<Double>(G.V());
distTo[s] = 0.0;
setDistancesToInfinityExceptS(s);
insertAllVertices(fringe);
/* Get vertices in order of distance from tree. */
while (!fringe.isEmpty()) {
int v = fringe.delMin();
scan(G, v);
}
}
while (!fringe.isEmpty()) {
int v = fringe.delMin();
scan(G, v);
}
private void scan(EdgeWeightedGraph G, int v) {
marked[v] = true;
for (Edge e : G.adj(v)) {
int w = e.other(v);//得到与点v接触的边e的另外一个节点
if (marked[w]) { continue; }
if (e.weight() < distTo[w]) {
distTo[w] = e.weight();
edgeTo[w] = e;
pq.decreasePriority(w, distTo[w]);//更新PQ中的weight值
}
}
}
Prim’s Algorithm Runtime
Kruskal’s Algorithm
initially mark all edges gray.
- Consider edges in increasing order of weight.
- Add edge to MST (mark black) unless doing so creates a cycle.
- Repeat until V-1 edges.
Conceptual Kruskal’s Algorithm Demo (Link) :
- Consider edges in order of increasing weight. Add to MST unless a cycle is created.
- Repeat until V-1 edges.
Realistic Kruskal’s Algorithm Implementation Demo (Link)
- Insert all edges into PQ.
- Repeat: Remove smallest weight edge. Add to MST if no cycle created.
WQU[]: weightQuickUnion,检查是否形成闭合回路,即在向MST中添加边AB之前,调用“connected(A,B)”,检查A,B两点是否已经在一个set中,若在一个set中,向MST中继续添加以AB为节点的边会造成MST形成闭合回路,故舍弃这个边。
Why does Kruskal’s work? Special case of generic MST algorithm.
- Suppose we add edge e = v->w.
- Side 1 of cut is all vertices connected to v, side 2 is everything else.
- No crossing edge is black (since we don’t allow cycles).
- No crossing edge has lower weight (consider in increasing order).
Kruskal’s Implementation (Pseudocode)
public class KruskalMST {
private List<Edge> mst = new ArrayList<Edge>();
public KruskalMST(EdgeWeightedGraph G) {
MinPQ<Edge> pq = new MinPQ<Edge>();
for (Edge e : G.edges()) {
pq.insert(e);
}
WeightedQuickUnionPC uf =
new WeightedQuickUnionPC(G.V());
while (!pq.isEmpty() && mst.size() < G.V() - 1) {
Edge e = pq.delMin();
int v = e.from();
int w = e.to();
if (!uf.connected(v, w)) {
uf.union(v, w);
mst.add(e);
} } } }