/// <summary> /// Produces a minimum spanning tree of the given graph using Prim's algorithm in O(E*ln E) time. /// Raises <exception cref="System.InvalidOperationException"> if the graph is not connected. /// </summary> /// <returns>Graph representation of the MST</returns> public static Graph <V> Prim <V>(Graph <V> graph) { if (graph == null) { throw new ArgumentNullException(); } if (!graph.IsConnected()) { throw new InvalidOperationException(); } // Lazy variant of Prim's algorithm: // Grow a tree by adding the smallest edge pointing out of it var tree = new Graph <V>(); var queue = new BinaryHeap <Edge <V> >(); var vertices = new HashSet <V>(); // vertices in the tree // Adds edges of v pointing out of the tree to the PQ void Visit(V v) { vertices.Add(v); foreach (var e in graph.Edges(v)) { if (!vertices.Contains(e.to)) { queue.Push(e); // If e.to is already in the tree then e (or rather its complement) is in the queue } } } if (!graph.IsEmpty()) { Visit(graph.Vertices().First()); } while (!queue.IsEmpty()) { var e = queue.Pop(); if (vertices.Contains(e.to)) { continue; // Otherwise we will form a cycle } tree.Add(e); Visit(e.to); } return(tree); }
/// <summary> /// Produces a minimum spanning tree of the given graph using Kruskal's algorithm in O(E*ln V) time. /// Raises <exception cref="System.InvalidOperationException"> if the graph is not connected. /// </summary> /// <returns>Graph representation of the MST</returns> public static Graph <V> Kruskal <V>(Graph <V> graph) { if (graph == null) { throw new ArgumentNullException(); } if (!graph.IsConnected()) { throw new InvalidOperationException(); // We would need to produce a minimum spanning forest instead } // Kruskal's algorithm is a special case of the greedy MST algorithm: // - Maintain a forest of trees (initially individual vertices of the graph) // - Repreatedly add edges in descending order of weight to combine forests into a tree // (Exclude edges that connect vertices that are already part of the same tree.) var tree = new Graph <V>(); var n = 0; // no. of vertices in the MST var queue = new BinaryHeap <Edge <V> >(); foreach (var e in graph.Edges()) { queue.Push(e); } var vertices = graph.Vertices(); var N = vertices.Count(); // no. of vertices in the original graph var uf = new QuickUnion <V>(vertices.ToArray()); // The MST of a connected graph must contain exactly N-1 edges while (n < N - 1) { var e = queue.Pop(); if (!uf.Connected(e.from, e.to)) { uf.Union(e.from, e.to); tree.Add(e); n++; } } return(tree); }