private IndexMinPQ<Double> pq; // priority queue of vertices /** * Computes a shortest-paths tree from the source vertex {@code s} to every * other vertex in the edge-weighted graph {@code G}. * * @param G the edge-weighted digraph * @param s the source vertex * @throws IllegalArgumentException if an edge weight is negative * @throws IllegalArgumentException unless {@code 0 <= s < V} */ public DijkstraUndirectedSP(EdgeWeightedGraph G, int s) { for (Edge e : G.edges()) { if (e.weight() < 0) throw new IllegalArgumentException("edge " + e + " has negative weight"); } distTo = new double[G.V()]; edgeTo = new Edge[G.V()]; validateVertex(s); for (int v = 0; v < G.V(); v++) distTo[v] = Double.POSITIVE_INFINITY; distTo[s] = 0.0; // relax vertices in order of distance from s pq = new IndexMinPQ<Double>(G.V()); pq.insert(s, distTo[s]); while (!pq.isEmpty()) { int v = pq.delMin(); for (Edge e : G.adj(v)) relax(e, v); } // check optimality conditions assert check(G, s); }
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); }
// 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; }
private MinPQ<Edge> pq; // edges with one endpoint in tree /** * Compute a minimum spanning tree (or forest) of an edge-weighted graph. * @param G the edge-weighted graph */ public LazyPrimMST(EdgeWeightedGraph G) { mst = new Queue<Edge>(); pq = new MinPQ<Edge>(); marked = new boolean[G.V()]; for (int v = 0; v < G.V(); v++) // run Prim from all vertices to if (!marked[v]) prim(G, v); // get a minimum spanning forest // check optimality conditions assert check(G); }
/** * Computes the connected components of the edge-weighted graph {@code G}. * * @param G the edge-weighted graph */ public CC(EdgeWeightedGraph G) { marked = new boolean[G.V()]; id = new int[G.V()]; size = new int[G.V()]; for (int v = 0; v < G.V(); v++) { if (!marked[v]) { dfs(G, v); count++; } } }
/** * Initializes a new edge-weighted graph that is a deep copy of {@code G}. * * @param G the edge-weighted graph to copy */ public EdgeWeightedGraph(EdgeWeightedGraph G) { this(G.V()); this.E = G.E(); for (int v = 0; v < G.V(); v++) { // reverse so that adjacency list is in same order as original Stack<Edge> reverse = new Stack<Edge>(); for (Edge e : G.adj[v]) { reverse.push(e); } for (Edge e : reverse) { adj[v].add(e); } } }
/** * Contracts the edges incidents on the vertices {@code s} and {@code t} of * the given edge-weighted graph. * * @param G the edge-weighted graph * @param s the vertex {@code s} * @param t the vertex {@code t} * @return a new edge-weighted graph for which the edges incidents on the * vertices {@code s} and {@code t} were contracted */ private EdgeWeightedGraph contractEdge(EdgeWeightedGraph G, int s, int t) { EdgeWeightedGraph H = new EdgeWeightedGraph(G.V()); for (int v = 0; v < G.V(); v++) { for (Edge e : G.adj(v)) { int w = e.other(v); if (v == s && w == t || v == t && w == s) continue; if (v < w) { if (w == t) H.addEdge(new Edge(v, s, e.weight())); else if (v == t) H.addEdge(new Edge(w, s, e.weight())); else H.addEdge(new Edge(v, w, e.weight())); } } } return H; }
/** * 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); } }
// check optimality conditions: // (i) for all edges e = v-w: distTo[w] <= distTo[v] + e.weight() // (ii) for all edge e = v-w on the SPT: distTo[w] == distTo[v] + e.weight() private boolean check(EdgeWeightedGraph G, int s) { // check that edge weights are nonnegative for (Edge e : G.edges()) { if (e.weight() < 0) { System.err.println("negative edge weight detected"); return false; } } // check that distTo[v] and edgeTo[v] are consistent if (distTo[s] != 0.0 || edgeTo[s] != null) { System.err.println("distTo[s] and edgeTo[s] inconsistent"); return false; } for (int v = 0; v < G.V(); v++) { if (v == s) continue; if (edgeTo[v] == null && distTo[v] != Double.POSITIVE_INFINITY) { System.err.println("distTo[] and edgeTo[] inconsistent"); return false; } } // check that all edges e = v-w satisfy distTo[w] <= distTo[v] + e.weight() for (int v = 0; v < G.V(); v++) { for (Edge e : G.adj(v)) { int w = e.other(v); if (distTo[v] + e.weight() < distTo[w]) { System.err.println("edge " + e + " not relaxed"); return false; } } } // check that all edges e = v-w on SPT satisfy distTo[w] == distTo[v] + e.weight() for (int w = 0; w < G.V(); w++) { if (edgeTo[w] == null) continue; Edge e = edgeTo[w]; if (w != e.either() && w != e.other(e.either())) return false; int v = e.other(w); if (distTo[v] + e.weight() != distTo[w]) { System.err.println("edge " + e + " on shortest path not tight"); return false; } } return true; }
/** * Returns the cut-of-the-phase. The cut-of-the-phase is a minimum s-t-cut * in the current graph, where {@code s} and {@code t} are the two vertices * added last in the phase. This algorithm is known in the literature as * <em>maximum adjacency search</em> or <em>maximum cardinality search</em>. * * @param G the edge-weighted graph * @param marked the array of contracted vertices, where {@code marked[v]} * is {@code true} if the vertex {@code v} was already * contracted; or {@code false} otherwise * @param cp the previous cut-of-the-phase * @return the cut-of-the-phase */ private CutPhase minCutPhase(EdgeWeightedGraph G, boolean[] marked, CutPhase cp) { IndexMaxPQ<Double> pq = new IndexMaxPQ<Double>(G.V()); for (int v = 0; v < G.V(); v++) { if (v != cp.s && !marked[v]) pq.insert(v, 0.0); } pq.insert(cp.s, Double.POSITIVE_INFINITY); while (!pq.isEmpty()) { int v = pq.delMax(); cp.s = cp.t; cp.t = v; for (Edge e : G.adj(v)) { int w = e.other(v); if (pq.contains(w)) pq.increaseKey(w, pq.keyOf(w) + e.weight()); } } cp.weight = 0.0; for (Edge e : G.adj(cp.t)) { cp.weight += e.weight(); } return cp; }
/** * Checks optimality conditions. * * @param G the edge-weighted graph * @return {@code true} if optimality conditions are fine */ private boolean check(EdgeWeightedGraph G) { // compute min st-cut for all pairs s and t // shortcut: s must appear on one side of global mincut, // so it suffices to try all pairs s-v for some fixed s double value = Double.POSITIVE_INFINITY; for (int s = 0, t = 1; t < G.V(); t++) { FlowNetwork F = new FlowNetwork(G.V()); for (Edge e : G.edges()) { int v = e.either(), w = e.other(v); F.addEdge(new FlowEdge(v, w, e.weight())); F.addEdge(new FlowEdge(w, v, e.weight())); } FordFulkerson maxflow = new FordFulkerson(F, s, t); value = Math.min(value, maxflow.value()); } if (Math.abs(weight - value) > FLOATING_POINT_EPSILON) { System.err.println("Min cut weight = " + weight + " , max flow value = " + value); return false; } return true; }
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); }
/** * Compute a minimum spanning tree (or forest) of an edge-weighted graph. * @param G the edge-weighted graph */ public PrimMST(EdgeWeightedGraph G) { edgeTo = new Edge[G.V()]; distTo = new double[G.V()]; marked = new boolean[G.V()]; pq = new IndexMinPQ<Double>(G.V()); for (int v = 0; v < G.V(); v++) distTo[v] = Double.POSITIVE_INFINITY; for (int v = 0; v < G.V(); v++) // run from each vertex to find if (!marked[v]) prim(G, v); // minimum spanning forest // check optimality conditions assert check(G); }
/** * Computes a minimum cut of an edge-weighted graph. * * @param G the edge-weighted graph * @throws IllegalArgumentException if the number of vertices of {@code G} * is less than {@code 2} or if anny edge weight is negative */ public GlobalMincut(EdgeWeightedGraph G) { V = G.V(); validate(G); minCut(G, 0); assert check(G); }
/** * Validates the edge-weighted graph. * * @param G the edge-weighted graph * @throws IllegalArgumentException if the number of vertices of {@code G} * is less than {@code 2} or if any edge weight is negative */ private void validate(EdgeWeightedGraph G) { if (G.V() < 2) throw new IllegalArgumentException("number of vertices of G is less than 2"); for (Edge e : G.edges()) { if (e.weight() < 0) throw new IllegalArgumentException("edge " + e + " has negative weight"); } }