Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CS253: Minimum Spanning Trees (2019)

Jinho D. Choi
October 30, 2019
190

CS253: Minimum Spanning Trees (2019)

Jinho D. Choi

October 30, 2019
Tweet

Transcript

  1. Types of Graphs 2 0 1 2 3 4 V

    E G = ( , ) Undirected
  2. Types of Graphs 2 0 1 2 3 4 V

    E G = ( , ) Undirected
  3. Types of Graphs 2 0 1 2 3 4 V

    E G = ( , ) Undirected Weighted
  4. Types of Graphs 2 0 1 2 3 4 3

    4 1 2 3 2 4 V E G = ( , ) Undirected Weighted
  5. Types of Graphs 2 0 1 2 3 4 3

    4 1 2 3 2 4 V E G = ( , ) Undirected Directed Weighted
  6. Types of Graphs 2 0 1 2 3 4 3

    4 1 2 3 2 4 V E G = ( , ) Undirected Directed Weighted
  7. Types of Graphs 2 0 1 2 3 4 3

    4 1 2 3 2 4 V E G = ( , ) Undirected Directed Weighted Acyclic
  8. Types of Graphs 2 0 1 2 3 4 3

    1 2 3 2 4 V E G = ( , ) Undirected Directed Weighted Acyclic
  9. Types of Graphs 2 0 1 2 3 4 3

    1 2 3 2 4 V E G = ( , ) Undirected Directed Weighted Acyclic Tree
  10. Types of Graphs 2 0 1 2 3 4 3

    1 2 3 2 4 V E G = ( , ) Undirected Directed Weighted Acyclic Tree Every node except for the root must have exactly one incoming edge.
  11. Types of Graphs 2 0 1 2 3 4 3

    1 2 2 V E G = ( , ) Undirected Directed Weighted Acyclic Tree Every node except for the root must have exactly one incoming edge.
  12. Types of Graphs 2 0 1 2 3 4 3

    1 2 2 V E G = ( , ) Undirected Directed Weighted Acyclic Tree Every node except for the root must have exactly one incoming edge. Every node must be reachable from the root.
  13. Types of Graphs 2 0 1 2 3 4 1

    2 2 V E G = ( , ) Undirected Directed Weighted Acyclic Tree Every node except for the root must have exactly one incoming edge. Every node must be reachable from the root.
  14. Types of Graphs 2 0 1 2 3 4 1

    2 2 V E G = ( , ) Undirected Directed Weighted Acyclic Tree Every node except for the root must have exactly one incoming edge. Every node must be reachable from the root. Forest
  15. Types of Graphs 2 0 1 2 3 4 1

    2 2 V E G = ( , ) Undirected Directed Weighted Acyclic Tree Every node except for the root must have exactly one incoming edge. Every node must be reachable from the root. Forest
  16. Undirected vs. Directed Graph 3 0 1 2 3 4

    Can we represent undirected graphs using directed graphs?
  17. Undirected vs. Directed Graph 3 0 1 2 3 4

    Can we represent undirected graphs using directed graphs?
  18. Edge 4 1 0 public class Edge implements Comparable<Edge> {

    private int source; private int target; private double weight; public Edge(int source, int target, double weight) { setSource(source); setTarget(target); setWeight(weight); } } 3.2
  19. Edge 4 1 0 public class Edge implements Comparable<Edge> {

    private int source; private int target; private double weight; public Edge(int source, int target, double weight) { setSource(source); setTarget(target); setWeight(weight); } } 3.2
  20. Edge 4 1 0 public class Edge implements Comparable<Edge> {

    private int source; private int target; private double weight; public Edge(int source, int target, double weight) { setSource(source); setTarget(target); setWeight(weight); } } by weight 3.2
  21. Edge 4 1 0 public class Edge implements Comparable<Edge> {

    private int source; private int target; private double weight; public Edge(int source, int target, double weight) { setSource(source); setTarget(target); setWeight(weight); } } by weight 3.2 public int compareTo(Edge edge) { double diff = weight - edge.weight; if (diff > 0) return 1; else if (diff < 0) return -1; else return 0; }
  22. Graph 5 public class Graph { private List<Edge>[] incoming_edges; public

    Graph(int size) { incoming_edges = (List<Edge>[])Stream.generate(ArrayList<Edge>::new) .limit(size).toArray(List<?>[]::new); } public List<Edge> getIncomingEdges(int target) { return incoming_edges[target]; } } 0 1 2
  23. Graph 5 public class Graph { private List<Edge>[] incoming_edges; public

    Graph(int size) { incoming_edges = (List<Edge>[])Stream.generate(ArrayList<Edge>::new) .limit(size).toArray(List<?>[]::new); } public List<Edge> getIncomingEdges(int target) { return incoming_edges[target]; } } 0 1 2
  24. Graph 5 public class Graph { private List<Edge>[] incoming_edges; public

    Graph(int size) { incoming_edges = (List<Edge>[])Stream.generate(ArrayList<Edge>::new) .limit(size).toArray(List<?>[]::new); } public List<Edge> getIncomingEdges(int target) { return incoming_edges[target]; } } 0 1 2 incoming_edges[0] = {}; incoming_edges[1] = {1 <- 0, 1 <- 2}; incoming_edges[2] = {2 <- 0};
  25. Graph 5 public class Graph { private List<Edge>[] incoming_edges; public

    Graph(int size) { incoming_edges = (List<Edge>[])Stream.generate(ArrayList<Edge>::new) .limit(size).toArray(List<?>[]::new); } public List<Edge> getIncomingEdges(int target) { return incoming_edges[target]; } } 0 1 2 incoming_edges[0] = {}; incoming_edges[1] = {1 <- 0, 1 <- 2}; incoming_edges[2] = {2 <- 0};
  26. Graph 5 public class Graph { private List<Edge>[] incoming_edges; public

    Graph(int size) { incoming_edges = (List<Edge>[])Stream.generate(ArrayList<Edge>::new) .limit(size).toArray(List<?>[]::new); } public List<Edge> getIncomingEdges(int target) { return incoming_edges[target]; } } 0 1 2 incoming_edges[0] = {}; incoming_edges[1] = {1 <- 0, 1 <- 2}; incoming_edges[2] = {2 <- 0}; getIncomingEdges(1);
  27. Graph 5 public class Graph { private List<Edge>[] incoming_edges; public

    Graph(int size) { incoming_edges = (List<Edge>[])Stream.generate(ArrayList<Edge>::new) .limit(size).toArray(List<?>[]::new); } public List<Edge> getIncomingEdges(int target) { return incoming_edges[target]; } } 0 1 2 incoming_edges[0] = {}; incoming_edges[1] = {1 <- 0, 1 <- 2}; incoming_edges[2] = {2 <- 0}; getIncomingEdges(1);
  28. Graph 6 public void setDirectedEdge(int source, int target, double weight)

    { List<Edge> edges = getIncomingEdges(target); edges.add(new Edge(source, target, weight)); } T S
  29. Graph 6 public void setDirectedEdge(int source, int target, double weight)

    { List<Edge> edges = getIncomingEdges(target); edges.add(new Edge(source, target, weight)); } T S
  30. Graph 6 public void setDirectedEdge(int source, int target, double weight)

    { List<Edge> edges = getIncomingEdges(target); edges.add(new Edge(source, target, weight)); } T S
  31. Graph 6 public void setDirectedEdge(int source, int target, double weight)

    { List<Edge> edges = getIncomingEdges(target); edges.add(new Edge(source, target, weight)); } T S
  32. Graph 6 public void setDirectedEdge(int source, int target, double weight)

    { List<Edge> edges = getIncomingEdges(target); edges.add(new Edge(source, target, weight)); } T S
  33. Graph 6 public void setDirectedEdge(int source, int target, double weight)

    { List<Edge> edges = getIncomingEdges(target); edges.add(new Edge(source, target, weight)); } public void setUndirectedEdge(int source, int target, double weight) { setDirectedEdge(source, target, weight); setDirectedEdge(target, source, weight); } T S
  34. Graph 6 public void setDirectedEdge(int source, int target, double weight)

    { List<Edge> edges = getIncomingEdges(target); edges.add(new Edge(source, target, weight)); } public void setUndirectedEdge(int source, int target, double weight) { setDirectedEdge(source, target, weight); setDirectedEdge(target, source, weight); } T S
  35. Graph 6 public void setDirectedEdge(int source, int target, double weight)

    { List<Edge> edges = getIncomingEdges(target); edges.add(new Edge(source, target, weight)); } public void setUndirectedEdge(int source, int target, double weight) { setDirectedEdge(source, target, weight); setDirectedEdge(target, source, weight); } T S
  36. Minimum Spanning Tree 8 GA NY CO IA TX $465

    $395 $178 $198 $490 $372 $270 $193 $446 $434
  37. Spanning Tree 9 public class SpanningTree implements Comparable<SpanningTree> { private

    List<Edge> edges; private double total_weight; public SpanningTree() { edges = new ArrayList<>(); } public void addEdge(Edge edge) { edges.add(edge); total_weight += edge.getWeight(); } } public int size() { return edges.size(); } public double getTotalWeight() { return total_weight; } public int compareTo(SpanningTree tree) { double diff = total_weight - tree.total_weight; if (diff > 0) return 1; else if (diff < 0) return -1; else return 0; }
  38. Spanning Tree 9 public class SpanningTree implements Comparable<SpanningTree> { private

    List<Edge> edges; private double total_weight; public SpanningTree() { edges = new ArrayList<>(); } public void addEdge(Edge edge) { edges.add(edge); total_weight += edge.getWeight(); } } public int size() { return edges.size(); } public double getTotalWeight() { return total_weight; } public int compareTo(SpanningTree tree) { double diff = total_weight - tree.total_weight; if (diff > 0) return 1; else if (diff < 0) return -1; else return 0; }
  39. Spanning Tree 9 public class SpanningTree implements Comparable<SpanningTree> { private

    List<Edge> edges; private double total_weight; public SpanningTree() { edges = new ArrayList<>(); } public void addEdge(Edge edge) { edges.add(edge); total_weight += edge.getWeight(); } } public int size() { return edges.size(); } public double getTotalWeight() { return total_weight; } public int compareTo(SpanningTree tree) { double diff = total_weight - tree.total_weight; if (diff > 0) return 1; else if (diff < 0) return -1; else return 0; }
  40. Prim’s Algorithm 10 0 1 2 3 4 3 4

    1 2 3 2 4 0 <- 3 0 <- 4
  41. Prim’s Algorithm 10 0 1 2 3 4 3 4

    1 2 3 2 4 0 <- 3 0 <- 4
  42. Prim’s Algorithm 10 0 1 2 3 4 3 4

    1 2 2 4 0 <- 3 0 <- 4
  43. Prim’s Algorithm 10 0 1 2 3 4 3 4

    1 2 2 4 0 <- 3 0 <- 4
  44. Prim’s Algorithm 10 0 1 2 3 4 3 4

    1 2 2 4 0 <- 3 0 <- 4 0 <- 1
  45. Prim’s Algorithm 10 0 1 2 3 4 3 4

    1 2 2 4 0 <- 3 0 <- 4 0 <- 1
  46. Prim’s Algorithm 10 0 1 2 3 4 3 4

    1 2 2 4 0 <- 3 0 <- 4 0 <- 1
  47. Prim’s Algorithm 10 0 1 2 3 4 3 4

    1 2 2 4 0 <- 3 0 <- 4 0 <- 1
  48. Prim’s Algorithm 10 0 1 2 3 4 3 4

    1 2 2 4 0 <- 3 0 <- 4 0 <- 1 1 <- 2
  49. Prim’s Algorithm 10 0 1 2 3 4 3 4

    1 2 2 4 0 <- 3 0 <- 4 0 <- 1 1 <- 2
  50. Prim’s Algorithm 10 0 1 2 3 4 3 4

    1 2 2 4 0 <- 3 0 <- 4 0 <- 1 1 <- 2 A spanning tree is found!
  51. Prim’s Algorithm 11 public SpanningTree getMinimumSpanningTree(Graph graph) { PriorityQueue<Edge> queue

    = new PriorityQueue<>(); SpanningTree tree = new SpanningTree(); Set<Integer> set = new HashSet<>(); Edge edge; add(queue, set, graph, 0); while (!queue.isEmpty()) { edge = queue.poll(); if (!set.contains(edge.getSource())) { tree.addEdge(edge); if (tree.size()+1 == graph.size()) break; add(queue, set, graph, edge.getSource()); } } return tree; }
  52. Prim’s Algorithm 11 public SpanningTree getMinimumSpanningTree(Graph graph) { PriorityQueue<Edge> queue

    = new PriorityQueue<>(); SpanningTree tree = new SpanningTree(); Set<Integer> set = new HashSet<>(); Edge edge; add(queue, set, graph, 0); while (!queue.isEmpty()) { edge = queue.poll(); if (!set.contains(edge.getSource())) { tree.addEdge(edge); if (tree.size()+1 == graph.size()) break; add(queue, set, graph, edge.getSource()); } } return tree; }
  53. Prim’s Algorithm 11 public SpanningTree getMinimumSpanningTree(Graph graph) { PriorityQueue<Edge> queue

    = new PriorityQueue<>(); SpanningTree tree = new SpanningTree(); Set<Integer> set = new HashSet<>(); Edge edge; add(queue, set, graph, 0); while (!queue.isEmpty()) { edge = queue.poll(); if (!set.contains(edge.getSource())) { tree.addEdge(edge); if (tree.size()+1 == graph.size()) break; add(queue, set, graph, edge.getSource()); } } return tree; }
  54. Prim’s Algorithm 11 public SpanningTree getMinimumSpanningTree(Graph graph) { PriorityQueue<Edge> queue

    = new PriorityQueue<>(); SpanningTree tree = new SpanningTree(); Set<Integer> set = new HashSet<>(); Edge edge; add(queue, set, graph, 0); while (!queue.isEmpty()) { edge = queue.poll(); if (!set.contains(edge.getSource())) { tree.addEdge(edge); if (tree.size()+1 == graph.size()) break; add(queue, set, graph, edge.getSource()); } } return tree; }
  55. Prim’s Algorithm 11 public SpanningTree getMinimumSpanningTree(Graph graph) { PriorityQueue<Edge> queue

    = new PriorityQueue<>(); SpanningTree tree = new SpanningTree(); Set<Integer> set = new HashSet<>(); Edge edge; add(queue, set, graph, 0); while (!queue.isEmpty()) { edge = queue.poll(); if (!set.contains(edge.getSource())) { tree.addEdge(edge); if (tree.size()+1 == graph.size()) break; add(queue, set, graph, edge.getSource()); } } return tree; } Complexity?
  56. Kruskal’s Algorithm 12 0 1 2 3 4 3 4

    1 2 3 2 4 0 <- 3 1 <- 2
  57. Kruskal’s Algorithm 12 0 1 2 3 4 3 4

    1 2 3 2 4 0 <- 3 1 <- 2
  58. Kruskal’s Algorithm 12 0 1 2 3 4 3 4

    1 2 3 2 4 0 <- 3 1 <- 2
  59. Kruskal’s Algorithm 12 0 1 2 3 4 3 4

    1 2 3 2 4 0 <- 3 1 <- 2 0 <- 4
  60. Kruskal’s Algorithm 12 0 1 2 3 4 3 4

    1 2 3 2 4 0 <- 3 1 <- 2 0 <- 4
  61. Kruskal’s Algorithm 12 0 1 2 3 4 3 4

    1 2 3 2 4 0 <- 3 1 <- 2 0 <- 4
  62. Kruskal’s Algorithm 12 0 1 2 3 4 3 4

    1 2 3 2 4 0 <- 3 1 <- 2 0 <- 4 0 <- 1
  63. Kruskal’s Algorithm 12 0 1 2 3 4 3 4

    1 2 3 2 4 0 <- 3 1 <- 2 0 <- 4 0 <- 1
  64. Kruskal’s Algorithm 13 public SpanningTree getMinimumSpanningTree(Graph graph) { PriorityQueue<Edge> queue

    = new PriorityQueue<>(graph.getAllEdges()); DisjointSet forest = new DisjointSet(graph.size()); SpanningTree tree = new SpanningTree(); Edge edge; while (!queue.isEmpty()) { edge = queue.poll(); if (!forest.inSameSet(edge.getTarget(), edge.getSource())) { tree.addEdge(edge); if (tree.size()+1 == graph.size()) break; forest.union(edge.getTarget(), edge.getSource()); } } return tree; }
  65. Kruskal’s Algorithm 13 public SpanningTree getMinimumSpanningTree(Graph graph) { PriorityQueue<Edge> queue

    = new PriorityQueue<>(graph.getAllEdges()); DisjointSet forest = new DisjointSet(graph.size()); SpanningTree tree = new SpanningTree(); Edge edge; while (!queue.isEmpty()) { edge = queue.poll(); if (!forest.inSameSet(edge.getTarget(), edge.getSource())) { tree.addEdge(edge); if (tree.size()+1 == graph.size()) break; forest.union(edge.getTarget(), edge.getSource()); } } return tree; }
  66. Kruskal’s Algorithm 13 public SpanningTree getMinimumSpanningTree(Graph graph) { PriorityQueue<Edge> queue

    = new PriorityQueue<>(graph.getAllEdges()); DisjointSet forest = new DisjointSet(graph.size()); SpanningTree tree = new SpanningTree(); Edge edge; while (!queue.isEmpty()) { edge = queue.poll(); if (!forest.inSameSet(edge.getTarget(), edge.getSource())) { tree.addEdge(edge); if (tree.size()+1 == graph.size()) break; forest.union(edge.getTarget(), edge.getSource()); } } return tree; }
  67. Kruskal’s Algorithm 13 public SpanningTree getMinimumSpanningTree(Graph graph) { PriorityQueue<Edge> queue

    = new PriorityQueue<>(graph.getAllEdges()); DisjointSet forest = new DisjointSet(graph.size()); SpanningTree tree = new SpanningTree(); Edge edge; while (!queue.isEmpty()) { edge = queue.poll(); if (!forest.inSameSet(edge.getTarget(), edge.getSource())) { tree.addEdge(edge); if (tree.size()+1 == graph.size()) break; forest.union(edge.getTarget(), edge.getSource()); } } return tree; }
  68. Proof by Induction 15 0 X n=0 = 0 ·

    1 2 = 0 Base Induction
  69. Proof by Induction 15 0 X n=0 = 0 ·

    1 2 = 0 Base Induction k X n=0 = k(k + 1) 2 Assume
  70. Proof by Induction 15 0 X n=0 = 0 ·

    1 2 = 0 Base Induction k X n=0 = k(k + 1) 2 Assume k X n=0 +(k + 1) = k(k + 1) 2 + (k + 1) = K2 + 3k + 2 2 = (k + 1)(k + 2) 2 Then,
  71. Proof by Contradiction 16 n2 = n · n =

    2k · 2k = 2(2 · 2k2) Contradiction
  72. Correctness of Prim’s Algorithm 18 0 1 2 3 4

    3 4 1 2 3 2 4 Prim’s algorithm finds e.
  73. Correctness of Prim’s Algorithm 18 0 1 2 3 4

    3 4 1 2 3 2 4 Prim’s algorithm finds e.
  74. Correctness of Prim’s Algorithm 18 0 1 2 3 4

    3 4 1 2 3 2 4 Prim’s algorithm finds e. Suppose that there exists another path p from T to 1 whose total weight < e.
  75. Correctness of Prim’s Algorithm 18 0 1 2 3 4

    3 4 1 2 3 2 4 Prim’s algorithm finds e. Suppose that there exists another path p from T to 1 whose total weight < e.
  76. Correctness of Prim’s Algorithm 18 0 1 2 3 4

    3 4 1 2 3 2 4 Prim’s algorithm finds e. Suppose that there exists another path p from T to 1 whose total weight < e. Then, all edges in p must have a weight < e.
  77. Correctness of Prim’s Algorithm 18 0 1 2 3 4

    3 4 1 2 3 2 4 Prim’s algorithm finds e. Suppose that there exists another path p from T to 1 whose total weight < e. Then, all edges in p must have a weight < e.
  78. Correctness of Prim’s Algorithm 18 0 1 2 3 4

    3 4 1 2 3 2 4 Prim’s algorithm finds e. Suppose that there exists another path p from T to 1 whose total weight < e. Then, all edges in p must have a weight < e. Proof by contradiction!
  79. Correctness of Kruskal’s Algorithm 20 0 1 2 3 4

    3 4 1 2 3 2 4 Kruskal’s algorithm finds e.
  80. Correctness of Kruskal’s Algorithm 20 0 1 2 3 4

    3 4 1 2 3 2 4 Kruskal’s algorithm finds e. Suppose that there exists another path p from Ts to Tt whose total weight < e.
  81. Correctness of Kruskal’s Algorithm 20 0 1 2 3 4

    3 4 1 2 3 2 4 Kruskal’s algorithm finds e. Suppose that there exists another path p from Ts to Tt whose total weight < e.
  82. Correctness of Kruskal’s Algorithm 20 0 1 2 3 4

    3 4 1 2 3 2 4 Kruskal’s algorithm finds e. Suppose that there exists another path p from Ts to Tt whose total weight < e. Then, all edges in p must have a weight < e.
  83. Correctness of Kruskal’s Algorithm 20 0 1 2 3 4

    3 4 1 2 3 2 4 Kruskal’s algorithm finds e. Suppose that there exists another path p from Ts to Tt whose total weight < e. Then, all edges in p must have a weight < e.
  84. Correctness of Kruskal’s Algorithm 20 0 1 2 3 4

    3 4 1 2 3 2 4 Kruskal’s algorithm finds e. Suppose that there exists another path p from Ts to Tt whose total weight < e. Then, all edges in p must have a weight < e. Proof by contradiction!
  85. Chu–Liu-Edmonds’ Algorithm 21 • Chu–Liu-Edmonds’ algorithm - Finding minimum spanning

    trees in directed graphs. • Algorithm 1. Initially, every vertex is considered a tree.
  86. Chu–Liu-Edmonds’ Algorithm 21 • Chu–Liu-Edmonds’ algorithm - Finding minimum spanning

    trees in directed graphs. • Algorithm 1. Initially, every vertex is considered a tree. 2. For each tree, keep 1 incoming edge with the minimum weight.
  87. Chu–Liu-Edmonds’ Algorithm 21 • Chu–Liu-Edmonds’ algorithm - Finding minimum spanning

    trees in directed graphs. • Algorithm 1. Initially, every vertex is considered a tree. 2. For each tree, keep 1 incoming edge with the minimum weight. 3. If there is no cycle, go to #5.
  88. Chu–Liu-Edmonds’ Algorithm 21 • Chu–Liu-Edmonds’ algorithm - Finding minimum spanning

    trees in directed graphs. • Algorithm 1. Initially, every vertex is considered a tree. 2. For each tree, keep 1 incoming edge with the minimum weight. 3. If there is no cycle, go to #5. 4. If there is a cycle, merge trees with the cycle into one and update scores for all incoming edges to this tree, and goto #2.
  89. Chu–Liu-Edmonds’ Algorithm 21 • Chu–Liu-Edmonds’ algorithm - Finding minimum spanning

    trees in directed graphs. • Algorithm 1. Initially, every vertex is considered a tree. 2. For each tree, keep 1 incoming edge with the minimum weight. 3. If there is no cycle, go to #5. 4. If there is a cycle, merge trees with the cycle into one and update scores for all incoming edges to this tree, and goto #2. • For each vertex in the tree, add the weight of its outgoing edge chain to its incoming edges not in the tree.
  90. Chu–Liu-Edmonds’ Algorithm 21 • Chu–Liu-Edmonds’ algorithm - Finding minimum spanning

    trees in directed graphs. • Algorithm 1. Initially, every vertex is considered a tree. 2. For each tree, keep 1 incoming edge with the minimum weight. 3. If there is no cycle, go to #5. 4. If there is a cycle, merge trees with the cycle into one and update scores for all incoming edges to this tree, and goto #2. • For each vertex in the tree, add the weight of its outgoing edge chain to its incoming edges not in the tree. 5. Break all cycles by removing edges that cause multiple parents.
  91. Chu–Liu-Edmonds’ Algorithm 22 0 1 2 3 4 20 10

    4 3 15 28 20 5 8 12 4 2 6 30 7 5 List<Set<Integer>> forest = initForest(graph.size());
  92. Chu–Liu-Edmonds’ Algorithm 22 0 1 2 3 4 20 10

    4 3 15 28 20 5 8 12 4 2 6 30 7 5 List<Set<Integer>> forest = initForest(graph.size());
  93. Chu–Liu-Edmonds’ Algorithm 23 0 1 2 3 4 20 10

    4 3 15 28 20 5 8 12 4 2 6 30 7 5 SpanningTree tree = 
 getMinimumIncomingEdges
 (graph, forest);
  94. Chu–Liu-Edmonds’ Algorithm 23 0 1 2 3 4 20 10

    4 3 15 28 20 5 8 12 4 2 6 30 7 5 SpanningTree tree = 
 getMinimumIncomingEdges
 (graph, forest);
  95. Chu–Liu-Edmonds’ Algorithm 24 0 1 2 3 4 20 10

    4 3 15 28 20 5 8 12 4 2 6 30 7 5 List<List<Edge>> cycles = tree.getCycles();
  96. Chu–Liu-Edmonds’ Algorithm 24 0 1 2 3 4 20 10

    4 3 15 28 20 5 8 12 4 2 6 30 7 5 List<List<Edge>> cycles = tree.getCycles();
  97. Chu–Liu-Edmonds’ Algorithm 25 0 1 2 3 4 20 10

    4 3 15 28 20 5 8 12 4 2 6 30 7 5 forest = updateEdgeWeights
 (graph, cycles);
  98. Chu–Liu-Edmonds’ Algorithm 25 0 1 2 3 4 20 10

    4 3 15 28 20 5 8 12 4 2 6 30 7 5 forest = updateEdgeWeights
 (graph, cycles); 3
  99. Chu–Liu-Edmonds’ Algorithm 25 0 1 2 3 4 20 10

    4 3 15 28 20 5 8 12 4 2 6 30 7 5 forest = updateEdgeWeights
 (graph, cycles); 3 23 8 8
  100. Chu–Liu-Edmonds’ Algorithm 25 0 1 2 3 4 20 10

    4 3 15 28 20 5 8 12 4 2 6 30 7 5 forest = updateEdgeWeights
 (graph, cycles); 3 23 8 8 2
  101. Chu–Liu-Edmonds’ Algorithm 25 0 1 2 3 4 20 10

    4 3 15 28 20 5 8 12 4 2 6 30 7 5 forest = updateEdgeWeights
 (graph, cycles); 3 23 8 8 6 10 2 32
  102. Chu–Liu-Edmonds’ Algorithm 26 0 1 2 3 4 20 10

    6 3 15 28 23 8 10 12 4 2 6 32 7 8 SpanningTree tree = 
 getMinimumIncomingEdges
 (graph, forest);
  103. Chu–Liu-Edmonds’ Algorithm 26 0 1 2 3 4 20 10

    6 3 15 28 23 8 10 12 4 2 6 32 7 8 SpanningTree tree = 
 getMinimumIncomingEdges
 (graph, forest);
  104. Chu–Liu-Edmonds’ Algorithm 27 0 1 2 3 4 20 10

    6 3 15 28 23 8 10 12 4 6 32 7 8 addEdgesFromCycles
 (tree, cyclicEdges); 2
  105. Chu–Liu-Edmonds’ Algorithm 27 0 1 2 3 4 20 10

    6 3 15 28 23 8 10 12 4 6 32 7 8 addEdgesFromCycles
 (tree, cyclicEdges); 2
  106. Chu–Liu-Edmonds’ Algorithm 28 0 1 2 3 4 4 1

    3 2 →5 →7 →6 4 Minimum Spanning Tree?