Minimum Spanning Trees: Prim-Jarnik & Kruskal
CS16: Introduction to Data Structures & Algorithms Spring 2020
Minimum Spanning Trees: Prim-Jarnik & Kruskal CS16: - - PowerPoint PPT Presentation
Minimum Spanning Trees: Prim-Jarnik & Kruskal CS16: Introduction to Data Structures & Algorithms Spring 2020 Outline Minimum Spanning Trees Prim-Jarnik Algorithm Analysis Proof of Correctness Kruskals Algorithm
Minimum Spanning Trees: Prim-Jarnik & Kruskal
CS16: Introduction to Data Structures & Algorithms Spring 2020
Outline
Spanning Trees
A B C E F D
5 4 4 3 8 6 4 2 4
Minimum Spanning Trees
A B C E F D
5 4 4 3 8 6 4 2 4
Applications
Minimum Spanning Tree Algos
6Minimum Spanning Tree Algos
7Minimum Spanning Tree Algos
8Prim-Jarnik Algorithm
them to MST
Example
10A B C E F D
5 4 4 3 8 6 4 2 4 ∞ null ∞ null ∞ null PQ = [(0,A),(∞,B),(∞,C),(∞,D),(∞,E),(∞,F)]
Random node set to cost 0
∞ null ∞ null null
Example
11A B C E F D
5 4 4 3 8 6 4 2 4 ∞ null 4 A ∞ null ∞ null 5 A null PQ = [(4,B),(5,D),(∞,C),(∞,E),(∞,F)]
Dequeue from PQ and update neighbors
Example
12A B C E F D
5 4 4 3 8 6 4 2 4 4 B 4 A 6 B 8 B 4 B null PQ = [(4,C),(4,D),(6,E),(8,F)]
Dequeue from PQ and update neighbors
Example
13A B C E F D
5 4 4 3 8 6 4 2 4 4 B 4 A 2 C 8 B 4 B null PQ = [(2,E),(4,D),(8,F)]
Dequeue from PQ and update neighbors
Example
14A B C E F D
5 4 4 3 8 6 4 2 4 4 B 4 A 2 C 4 E 4 B null PQ = [(4,D),(4,F)]
Dequeue from PQ and update neighbors
Example
15A B C E F D
5 4 4 3 8 6 4 2 4 4 B 4 A 2 C 3 D 4 B null PQ = [(3,F)]
Dequeue from PQ and update neighbors
Example
16A B C E F D
5 4 4 3 8 6 4 2 4 4 B 4 A 2 C 3 D 4 B null PQ = [ ]
Dequeue from PQ and update neighbors
Example
17A B C E F D
5 4 4 3 8 6 4 2 4 4 B 4 A 2 C 3 D 4 B null
Pseudo-code
18 function prim(G): // Input: weighted, undirected graph G with vertices V // Output: list of edges in MST for all v in V: v.cost = ∞ v.prev = null s = a random v in V // pick a random source s s.cost = 0 MST = [] PQ = PriorityQueue(V) // priorities will be v.cost values while PQ is not empty: v = PQ.removeMin() if v.prev != null: MST.append((v, v.prev)) for all incident edges (v,u) of v such that u is in PQ: if u.cost > (v,u).weight: u.cost = (v,u).weight u.prev = v PQ.decreaseKey(u, u.cost) return MSTSimulate Prim-Jarnik
Activity #1
function prim(G): // Input: weighted, undirected graph G with vertices V // Output: list of edges in MST for all v in V: v.cost = ∞ v.prev = null s = a random v in V // pick a random source s s.cost = 0 MST = [] PQ = PriorityQueue(V) // priorities will be v.cost values while PQ is not empty: v = PQ.removeMin() if v.prev != null: //guarantees we don’t add (s, s.prev) MST.append((v, v.prev)) for all incident edges (v,u) of v such that u is in PQ: if u.cost > (v,u).weight: u.cost = (v,u).weight u.prev = v PQ.decreaseKey(u, u.cost) return MSTSimulate Prim-Jarnik
Activity #1
function prim(G): // Input: weighted, undirected graph G with vertices V // Output: list of edges in MST for all v in V: v.cost = ∞ v.prev = null s = a random v in V // pick a random source s s.cost = 0 MST = [] PQ = PriorityQueue(V) // priorities will be v.cost values while PQ is not empty: v = PQ.removeMin() if v.prev != null: //guarantees we don’t add (s, s.prev) MST.append((v, v.prev)) for all incident edges (v,u) of v such that u is in PQ: if u.cost > (v,u).weight: u.cost = (v,u).weight u.prev = v PQ.decreaseKey(u, u.cost) return MSTSimulate Prim-Jarnik
Activity #1
function prim(G): // Input: weighted, undirected graph G with vertices V // Output: list of edges in MST for all v in V: v.cost = ∞ v.prev = null s = a random v in V // pick a random source s s.cost = 0 MST = [] PQ = PriorityQueue(V) // priorities will be v.cost values while PQ is not empty: v = PQ.removeMin() if v.prev != null: //guarantees we don’t add (s, s.prev) MST.append((v, v.prev)) for all incident edges (v,u) of v such that u is in PQ: if u.cost > (v,u).weight: u.cost = (v,u).weight u.prev = v PQ.decreaseKey(u, u.cost) return MSTSimulate Prim-Jarnik
Activity #1
function prim(G): // Input: weighted, undirected graph G with vertices V // Output: list of edges in MST for all v in V: v.cost = ∞ v.prev = null s = a random v in V // pick a random source s s.cost = 0 MST = [] PQ = PriorityQueue(V) // priorities will be v.cost values while PQ is not empty: v = PQ.removeMin() if v.prev != null: //guarantees we don’t add (s, s.prev) MST.append((v, v.prev)) for all incident edges (v,u) of v such that u is in PQ: if u.cost > (v,u).weight: u.cost = (v,u).weight u.prev = v PQ.decreaseKey(u, u.cost) return MSTSimulate Prim-Jarnik
Activity #1
function prim(G): // Input: weighted, undirected graph G with vertices V // Output: list of edges in MST for all v in V: v.cost = ∞ v.prev = null s = a random v in V // pick a random source s s.cost = 0 MST = [] PQ = PriorityQueue(V) // priorities will be v.cost values while PQ is not empty: v = PQ.removeMin() if v.prev != null: //guarantees we don’t add (s, s.prev) MST.append((v, v.prev)) for all incident edges (v,u) of v such that u is in PQ: if u.cost > (v,u).weight: u.cost = (v,u).weight u.prev = v PQ.decreaseKey(u, u.cost) return MSTRuntime of Prim-Jarnik
24Activity #2
Runtime of Prim-Jarnik
25Activity #2
Runtime of Prim-Jarnik
26Activity #2
Runtime of Prim-Jarnik
27Activity #2
Runtime Analysis
Proof of Correctness
Inductive invariant for Prim
edges added so far
Inductive invariant for Prim
edges added so far
subtree of some MST
31Graph Cuts
a b
Proof of Correctness
T M
IH
Proof of Correctness
T
Proof of Correctness
M T e
IH
Proof of Correctness
T e e’ M e e’
IH
Proof of Correctness
by Prim’s
37T e e’ M’
Proof of Correctness
cases)
some MST
38Outline
Kruskal’s Algorithm
Example
41A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(C,E),(D,F),(B,C),(E,F),(B,D),(A,B),(A,D),(B,E),(B,F)]Simulate Kruskal
42Activity #3
Simulate Kruskal
43Activity #3
Simulate Kruskal
44Activity #3
Simulate Kruskal
45Activity #3
Kruskal
cloud
Example
47A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(C,E),(D,F),(B,C),(E,F),(B,D),(A,B),(A,D),(B,E),(B,F)]Example
48A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(D,F),(B,C),(E,F),(B,D),(A,B),(A,D),(B,E),(B,F)]Example
49A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(B,C),(E,F),(B,D),(A,B),(A,D),(B,E),(B,F)]Example
50A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(E,F),(B,D),(A,B),(A,D),(B,E),(B,F)]Example
51A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(B,D),(A,B),(A,D),(B,E),(B,F)]Example
52A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(A,B),(A,D),(B,E),(B,F)]BD cannot be added because it would lead to a cycle
Example
53A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(A,D),(B,E),(B,F)]Example
54A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(B,E),(B,F)]AD cannot be added because it would lead to a cycle
Example
55A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(B,F)]BE cannot be added because it would lead to a cycle
Example
56A B C E F D
5 4 4 3 8 6 4 2 4
edges = [ ]BF cannot be added because it would lead to a cycle
Kruskal Pseudo-Code
57 function kruskal(G): // Input: undirected, weighted graph G // Output: list of edges in MST for vertices v in G: makeCloud(v) // put every vertex into it own set MST = [] Sort all edges for all edges (u,v) in G sorted by weight: if u and v are not in same cloud: add (u,v) to MST merge clouds containing u and v return MSTMerging Clouds (Naive way)
cloud’s number
58Merging Clouds (Naive way)
Runtime of Naive Kruskal
60Activity #4
Runtime of Naive Kruskal
61Activity #4
Runtime of Naive Kruskal
62Activity #4
Runtime of Naive Kruskal
63Activity #4
Kruskal Runtime w/ Naive Clouds
64 function kruskal(G): // Input: undirected, weighted graph G // Output: list of edges in MST for vertices v in G: makeCloud(v) MST = [] Sort all edges for all edges (u,v) in G sorted by weight: if u and v are not in same cloud: add (u,v) to MST merge clouds containing u and v return MSTO(|E|log|E|) O(|E|) O(|V|) O(|V|)
Kruskal Runtime
merging clouds naively
since |E| ≤ |V|2
Union-Find
Example
67A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(C,E),(D,F),(B,C),(E,F),(B,D),(A,B),(A,D),(B,E),(B,F)]Example
68A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(D,F),(B,C),(E,F),(B,D),(A,B),(A,D),(B,E),(B,F)]Example
69A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(B,C),(E,F),(B,D),(A,B),(A,D),(B,E),(B,F)]Example
70A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(E,F),(B,D),(A,B),(A,D),(B,E),(B,F)]Example
71A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(B,D),(A,B),(A,D),(B,E),(B,F)]Example
72A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(A,D),(B,E),(B,F)]Example
73A B C E F D
5 4 4 3 8 6 4 2 4
edges = [(A,D),(B,E),(B,F)]Implementing Union-Find
A B
Implementing Union-Find
A B
Cloud 1 Cloud 2
Implementing Union-Find
Implementing Union-Find
A B C D E F G H
1 1
Implementing Union-Find
A B C D E F G H
2 1
Implementing Union-Find
A B C D
1
E
Implementing Union-Find
A B C D
1
E A B C D
1
E
2
Implementing Union-Find
81 // Merges two clouds, given the root of each cloud function union(root1, root2): if root1.rank > root2.rank: root2.parent = root1 elif root1.rank < root2.rank: root1.parent = root2 else: root2.parent = root1 root1.rank++Implementing Union-Find
A B
1
Path Compression
Path Compression
A B C D A B C D
Amortized O(1)
O(log|V|)Path Compression Pseudo-code
85 function find_root(x): if x.parent != x: x.parent = find_root(x.parent) return x.parentRuntime of Kruskal w/ Path Compression
86Activity #5
Runtime of Kruskal w/ Path Compression
87Activity #5
Runtime of Kruskal w/ Path Compression
88Activity #5
Runtime of Kruskal w/ Path Compression
89 function kruskal(G): // Input: undirected, weighted graph G // Output: list of edges in MST for vertices v in G: makeCloud(v) MST = [] Sort all edges for all edges (u,v) in G sorted by weight: if u and v are not in same cloud: add (u,v) to MST merge clouds containing u and v return MSTO(|E|log|E|) O(|E|) O(1) amortized O(|V|)
Kruskal Runtime
merging clouds with path compression
Readings