private LinkedQueue <Edge> mst = new LinkedQueue <Edge>(); // edges in MST /// <summary> /// Compute a minimum spanning tree (or forest) of an edge-weighted graph.</summary> /// <param name="G">the edge-weighted graph</param> /// public KruskalMST(EdgeWeightedGraph G) { // more efficient to build heap by passing array of edges MinPQ <Edge> pq = new MinPQ <Edge>(); foreach (Edge e in G.Edges()) { pq.Insert(e); } // run greedy algorithm UF uf = new UF(G.V); while (!pq.IsEmpty && mst.Count < G.V - 1) { Edge e = pq.DelMin(); int v = e.Either; int w = e.Other(v); if (!uf.Connected(v, w)) { // v-w does not create a cycle uf.Union(v, w); // merge v and w components mst.Enqueue(e); // add edge e to mst weight += e.Weight; } } // check optimality conditions Debug.Assert(check(G)); }
private double weight; // weight of MST /// <summary> /// Compute a minimum spanning tree (or forest) of an edge-weighted graph.</summary> /// <param name="G">the edge-weighted graph</param> /// public BoruvkaMST(EdgeWeightedGraph G) { UF uf = new UF(G.V); // repeat at most log V times or until we have V-1 edges for (int t = 1; t < G.V && mst.Count < G.V - 1; t = t + t) { // foreach tree in forest, find closest edge // if edge weights are equal, ties are broken in favor of first edge in G.edges() Edge[] closest = new Edge[G.V]; foreach (Edge e in G.Edges()) { int v = e.Either, w = e.Other(v); int i = uf.Find(v), j = uf.Find(w); if (i == j) { continue; // same tree } if (closest[i] == null || less(e, closest[i])) { closest[i] = e; } if (closest[j] == null || less(e, closest[j])) { closest[j] = e; } } // add newly discovered edges to MST for (int i = 0; i < G.V; i++) { Edge e = closest[i]; if (e != null) { int v = e.Either, w = e.Other(v); // don't add the same edge twice if (!uf.Connected(v, w)) { mst.Add(e); weight += e.Weight; uf.Union(v, w); } } } } // check optimality conditions Debug.Assert(check(G)); }
public static void MainTest(string[] args) { TextInput StdIn = new TextInput(); int N = StdIn.ReadInt(); UF uf = new UF(N); while (!StdIn.IsEmpty) { int p = StdIn.ReadInt(); int q = StdIn.ReadInt(); if (uf.Connected(p, q)) { continue; } uf.Union(p, q); Console.WriteLine(p + " " + q); } Console.WriteLine(uf.Count + " components"); }
// check optimality conditions (takes time proportional to E V lg* V) private bool check(EdgeWeightedGraph G) { // check total weight double total = 0.0; foreach (Edge e in Edges()) { total += e.Weight; } if (Math.Abs(total - Weight) > FLOATING_POINT_EPSILON) { Console.Error.Write("Weight of edges does not equal Weight: {0} vs. {0}\n", total, Weight); return(false); } // check that it is acyclic UF uf = new UF(G.V); foreach (Edge e in Edges()) { int v = e.Either, w = e.Other(v); if (uf.Connected(v, w)) { Console.Error.WriteLine("Not a forest"); return(false); } uf.Union(v, w); } // check that it is a spanning forest foreach (Edge e in G.Edges()) { int v = e.Either, w = e.Other(v); if (!uf.Connected(v, w)) { Console.Error.WriteLine("Not a spanning forest"); return(false); } } // check that it is a minimal spanning forest (cut optimality conditions) foreach (Edge e in Edges()) { // all edges in MST except e uf = new UF(G.V); foreach (Edge f in mst) { int x = f.Either, y = f.Other(x); if (f != e) { uf.Union(x, y); } } // check that e is min weight edge in crossing cut foreach (Edge f in G.Edges()) { int x = f.Either, y = f.Other(x); if (!uf.Connected(x, y)) { if (f.Weight < e.Weight) { Console.Error.WriteLine("Edge " + f + " violates cut optimality conditions"); return(false); } } } } return(true); }