Beispiel #1
0
    private double weight;                      // weight of MST

    /**
     * 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.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()
            Edge[] closest = new Edge[G.V()];
            for (Edge e : 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
        assert check(G);
    }
Beispiel #2
0
    // check optimality conditions (takes time proportional to E V lg* V)
    private boolean check(EdgeWeightedGraph G) {

        // check weight
        double totalWeight = 0.0;
        for (Edge e : edges()) {
            totalWeight += e.weight();
        }
        if (Math.abs(totalWeight - weight()) > FLOATING_POINT_EPSILON) {
            System.err.printf("Weight of edges does not equal weight(): %f vs. %f\n", totalWeight, weight());
            return false;
        }

        // check that it is acyclic
        UF uf = new UF(G.V());
        for (Edge e : edges()) {
            int v = e.either(), w = e.other(v);
            if (uf.connected(v, w)) {
                System.err.println("Not a forest");
                return false;
            }
            uf.union(v, w);
        }

        // check that it is a spanning forest
        for (Edge e : G.edges()) {
            int v = e.either(), w = e.other(v);
            if (!uf.connected(v, w)) {
                System.err.println("Not a spanning forest");
                return false;
            }
        }

        // check that it is a minimal spanning forest (cut optimality conditions)
        for (Edge e : edges()) {

            // all edges in MST except e
            uf = new UF(G.V());
            for (Edge f : edges()) {
                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
            for (Edge f : G.edges()) {
                int x = f.either(), y = f.other(x);
                if (!uf.connected(x, y)) {
                    if (f.weight() < e.weight()) {
                        System.err.println("Edge " + f + " violates cut optimality conditions");
                        return false;
                    }
                }
            }

        }

        return true;
    }
Beispiel #3
0
 /**
  * Reads in a an integer {@code n} and a sequence of pairs of integers
  * (between {@code 0} and {@code n-1}) from standard input, where each integer
  * in the pair represents some site;
  * if the sites are in different components, merge the two components
  * and print the pair to standard output.
  *
  * @param args the command-line arguments
  */
 public static void main(String[] args) {
     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);
         StdOut.println(p + " " + q);
     }
     StdOut.println(uf.count() + " components");
 }
Beispiel #4
0
 /**
  * Computes a minimum cut of the edge-weighted graph. Precisely, it computes
  * the lightest of the cuts-of-the-phase which yields the desired minimum
  * cut.
  * 
  * @param G the edge-weighted graph
  * @param a the starting vertex
  */
 private void minCut(EdgeWeightedGraph G, int a) {
     UF uf = new UF(G.V());
     boolean[] marked = new boolean[G.V()];
     cut = new boolean[G.V()];
     CutPhase cp = new CutPhase(0.0, a, a);
     for (int v = G.V(); v > 1; v--) {
         cp = minCutPhase(G, marked, cp);
         if (cp.weight < weight) {
             weight = cp.weight;
             makeCut(cp.t, uf);
         }
         G = contractEdge(G, cp.s, cp.t);
         marked[cp.t] = true;
         uf.union(cp.s, cp.t);
     }
 }
Beispiel #5
0
    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>();
        for (Edge e : 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.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
        assert check(G);
    }
Beispiel #6
0
 /**
  * Makes a cut for the current edge-weighted graph by partitioning its set
  * of vertices into two nonempty subsets. The vertices connected to the
  * vertex {@code t} belong to the first subset. Other vertices not connected
  * to {@code t} belong to the second subset.
  * 
  * @param t the vertex {@code t}
  * @param uf the union-find data type
  */
 private void makeCut(int t, UF uf) {
     for (int v = 0; v < cut.length; v++) {
         cut[v] = uf.connected(v, t);
     }
 }