// check optimality conditions (takes time proportional to E V lg* V) private boolean check(EdgeWeightedGraph G) { // check total weight double total = 0.0; for (Edge e : edges()) { total += e.weight(); } double EPSILON = 1E-12; if (Math.abs(total - weight()) > EPSILON) { System.err.printf("Weight of edges does not equal weight(): %f vs. %f\n", total, 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 : 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()) { int v = e.either(), w = e.other(v); // all edges in MST except e uf = new UF(G.V()); for (Edge f : 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 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; }
/** @param args */ public static void main(String[] args) { try { int N = StdIn.readInt(); indexArray = new int[N]; for (int i = 0; i < N; i++) { indexArray[i] = i; } UF uf = new WeightedQuickUnionUF(N); while (!StdIn.isEmpty()) { int p = StdIn.readInt(); if (p == -1) { p = StdIn.readInt(); int q = StdIn.readInt(); StdOut.print(p + " and " + q + " are"); if (!uf.connected(p, q)) { StdOut.print(" not"); } StdOut.println(" connected."); } else { int q = StdIn.readInt(); if (!uf.connected(p, q)) { uf.union(p, q); StdOut.println("connecting " + p + " " + q); } } printArray(indexArray); printArray(uf.idArray()); printArray(uf.sizeArray()); StdOut.println(); } } catch (InputMismatchException e) { System.exit(0); } }
/** * Find k clusters in given graph. Returns maximum spacing between clusters. * * @param k - number of cluster to find * @return spacing between clusters */ public int findClusters(final int k) { Preconditions.checkArgument(k >= 2); final Edge[] edges = g.getEdges(); Arrays.sort(edges); final UF uf = new UF(g.getVertexCount()); for (Edge edge : edges) { if (uf.connected(edge.from, edge.to)) continue; if (uf.count() > k) uf.union(edge.from, edge.to); else return edge.weight; } throw new IllegalStateException("Failed to reach " + k + " clusters. This should not happen."); }
public static void main(String[] args) { int N = StdIn.readInt(); UF uf = new UF(N); // read in a sequence of pairs of integers (each in the range 0 to N-1), // calling find() for each pair: If the members of the pair are not already // call union() and print the pair. 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("# components: " + uf.count()); }
public static void main(String[] args) { StdOut.println("Quick-union-weighted"); 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)) { uf.union(p, q); // StdOut.println(p + " " + q); StdOut.println(uf); } } }
public KruskalMST(EdgeWeightedGraph G) { mst = new Queue<Edge>(); MaxPQ<Edge> pq = new MaxPQ<Edge>(); for (Edge e : G.edges()) pq.insert(e); // 将所有的边进入优先队列,按照权重升序排列 UF uf = new UF(G.V()); // 构建union-find对象 while (!pq.isEmpty() && mst.size() < G.V() - 1) { Edge e = pq.delMax(); // 从pq得到权重最小的边和他的顶点 int v = e.either(), w = e.other(v); if (uf.connected(v, w)) continue; // 忽略失效的边,两个顶点已经在生成树中了 uf.union(v, w); // 否则将两者合并,在一个树中,顶点 mst.enqueue(e); // 将边添加到最小生成树中 } }
KruskalMST(EdgeWeightedGraph G) { MinPQ<Edge> pq = new MinPQ<Edge>(); // we dont need to pass a new comparator let it // follow the natural ordering of edges double temp_wt = 0; for (Edge e : G.edges()) pq.insert(e); UF set = 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 (!set.connected(v, w)) { set.union(v, w); mst.add(e); temp_wt += e.weight(); } } this.weight = temp_wt; }
// Kruskal's algorithm 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); }
/** * Dado un grafo no dirigido y con pesos, ejecuta el algoritmo de Kruskal para la obtención del su * árbol de cobertura mínima. * * @param G Grafo no dirigido con pesos al cual se le deesea obtener su arbol de cobertura mínima. */ public void minimumSpanningTree(EdgeWeightedGraph G) // By Kruskal's algorithm { LinkedList<Edge> mst = new LinkedList<>(); MinPQ<Edge> pq = new MinPQ<>(G.E()); for (Edge edge : G.edges()) // Bag<Edge> != Comparator<Edge> :c pq.insert(edge); UF uf = new UF(G.V()); while (!pq.isEmpty() && mst.size() < G.V() - 1) { Edge edge = pq.delMin(); int v = edge.either(), w = edge.other(v); if (!uf.connected(v, w)) { uf.union(v, w); mst.add(edge); } } System.out.println(""); for (Edge edge : mst) System.out.println(edge); }