private readonly Collections.Queue <EdgeW> _mst = new Collections.Queue <EdgeW>(); // edges in MST /// <summary> /// Compute a minimum spanning tree (or forest) of an edge-weighted graph. /// </summary> /// <param name="g">g the edge-weighted graph</param> public KruskalMST(EdgeWeightedGraph g) { // more efficient to build heap by passing array of edges var pq = new MinPQ <EdgeW>(); foreach (var e in g.Edges()) { pq.Insert(e); } // run greedy algorithm var uf = new UF(g.V); while (!pq.IsEmpty() && _mst.Size() < g.V - 1) { var e = pq.DelMin(); var v = e.Either(); var 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 //assert check(G); }
private readonly double _weight; // weight of MST /// <summary> /// Compute a minimum spanning tree (or forest) of an edge-weighted graph. /// </summary> /// <param name="g">g the edge-weighted graph</param> public BoruvkaMST(EdgeWeightedGraph g) { var uf = new UF(g.V); // repeat at most log V times or until we have V-1 edges for (var t = 1; t < g.V && _mst.Size() < 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() var closest = new EdgeW[g.V]; foreach (var 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 (var i = 0; i < g.V; i++) { var 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); }
private UF Union(Tuple <int, int>[] links, int N) { UF uf = new UF(N); foreach (var pair in links) { int p = pair.Item1; int q = pair.Item2; if (uf.Connected(p, q)) { continue; } uf.Union(pair.Item1, pair.Item2); } return(uf); }
public KruskalMST(EdgeWeightedGraph g) { _mst = new Queue <Edge>(); var pq = new MinPQ <Edge>(g.E); foreach (var e in g.Edges()) { pq.Insert(e); } var uf = new UF(g.V); while (!pq.IsEmpty && _mst.Count < g.V - 1) { var e = (Edge)pq.DeleteMin(); int v = e.Either(), w = e.Other(v); if (uf.Connected(v, w)) { continue; } uf.Union(v, w); _mst.Enqueue(e); } }
public KruskalMST(IEdgeWeightGraph G) { mst = new Chapter1.Queue <IEdge>(); MinPQ <IEdge> pq = new MinPQ <IEdge>(); foreach (var e in G.Edges()) { pq.Insert(e); } UF uf = new UF(G.V); while (!pq.IsEmpty && mst.Size < G.V - 1) { IEdge e = pq.Delete(); //找到权重最小的边 int v = e.Either, w = e.Other(v); if (uf.Connected(v, w)) //忽略失效的边 { continue; } uf.Union(v, w); mst.Enqueue(e); } }
/// <summary> /// check optimality conditions (takes time proportional to E V lg* V) /// </summary> /// <param name="g"></param> /// <returns></returns> public bool Check(EdgeWeightedGraph g) { // check total weight var total = Edges().Sum(e => e.Weight); if (Math.Abs(total - Weight()) > FLOATING_POINT_EPSILON) { Console.Error.WriteLine($"Weight of edges does not equal weight(): {total} vs. {Weight()}{Environment.NewLine}"); return(false); } // check that it is acyclic var uf = new UF(g.V); foreach (var 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 (var 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 (var e in Edges()) { // all edges in MST except e uf = new UF(g.V); foreach (var 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 (var 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); }