private Queue <Edge> mst = new Queue <Edge>(); // edges in MST /** * Compute a minimum spanning tree (or forest) of an edge-weighted graph. * @param G the edge-weighted graph */ 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.Size < G.V - 1) { Edge e = pq.DeleteMin(); int v = e.Either; int w = e.other(v); if (!uf.Connected(v, w)) { // v-w does not create a cycle // merge v and w components uf.Union(v, w); mst.Enqueue(e); // add edge e to mst weight += e.Weight; } } // check optimality conditions //assert ; Contract.Assert(check(G)); }
/** * Compute a minimum spanning tree (or forest) of an edge-weighted graph. * @param G the edge-weighted graph */ 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 || e < closest[i]) { closest[i] = e; } if (closest[j] == null || 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 //assert check(G); Contract.Assert(check(G)); }
public void OptimalAlgorithm_UF_StepByStep_Tuples() { UF uF = new UF(10); for (int i = 0; i < 10; i++) { int p = tuples[i, 0]; int q = tuples[i, 1]; if (!uF.Connected(p, q)) { uF.Union(p, q); } switch (i) { case 0: Assert.True(uF.Connected(4, 3)); Assert.Equal(4, uF.Ids[3]); Assert.Equal(1, uF.Ranks[4]); Assert.Equal(0, uF.Ranks[3]); break; case 1: Assert.True(uF.Connected(8, 3)); Assert.True(uF.Connected(8, 4)); Assert.Equal(4, uF.Ids[3]); Assert.Equal(4, uF.Ids[8]); Assert.Equal(1, uF.Ranks[4]); Assert.Equal(0, uF.Ranks[8]); break; case 2: Assert.True(uF.Connected(6, 5)); Assert.Equal(6, uF.Ids[5]); Assert.Equal(1, uF.Ranks[6]); Assert.Equal(0, uF.Ranks[5]); break; case 3: Assert.True(uF.Connected(4, 9)); Assert.Equal(4, uF.Ids[9]); Assert.Equal(1, uF.Ranks[4]); Assert.Equal(0, uF.Ranks[9]); break; case 4: Assert.True(uF.Connected(2, 1)); Assert.Equal(2, uF.Ids[1]); Assert.Equal(1, uF.Ranks[2]); Assert.Equal(0, uF.Ranks[1]); break; case 5: Assert.True(uF.Connected(8, 9)); Assert.Equal(4, uF.Ids[9]); Assert.Equal(4, uF.Ids[8]); break; case 6: Assert.True(uF.Connected(5, 0)); Assert.Equal(6, uF.Ids[5]); Assert.Equal(6, uF.Ids[0]); break; case 7: Assert.True(uF.Connected(7, 2)); Assert.Equal(2, uF.Ids[7]); break; case 8: Assert.True(uF.Connected(6, 1)); Assert.Equal(6, uF.Ids[1]); Assert.Equal(2, uF.Ranks[6]); break; case 9: Assert.True(uF.Connected(7, 3)); Assert.Equal(6, uF.Ids[4]); Assert.Equal(6, uF.Ids[7]); Assert.Equal(6, uF.Ids[3]); break; default: break; } } // at the end Assert.Equal(new byte[] { 0, 0, 1, 0, 1, 0, 2, 0, 0, 0 }, uF.Ranks); Assert.Equal(new[] { 6, 6, 6, 6, 6, 6, 6, 6, 4, 4 }, uF.Ids); Assert.Equal(1, uF.Count); }