import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static void main
(String[] args
) { // Wikipediaのサンプルグラフ
Kruskal.Graph g = new Kruskal.Graph(
new int[][]{
{0, 1, 7},
{0, 3, 5},
{1, 2, 8},
{1, 3, 9},
{1, 4, 7},
{2, 4, 5},
{3, 4, 15},
{3, 5, 6},
{4, 5, 8},
{4, 6, 9},
{5, 6, 11},
}
);
int cost = 0;
Kruskal k = new Kruskal();
for(Kruskal.Edge e : k.getMinimumSpanningTreeEdges(g)) {
System.
out.
println(e.
u + ", " + e.
v + ", " + e.
c); cost += e.c;
}
System.
out.
println("cost : " + cost
); }
}
class Kruskal {
public List<Edge> getMinimumSpanningTreeEdges(Graph graph) {
List<Edge> result = new ArrayList<Edge>();
List<Edge> edges = graph.getEdges();
UnionFindTree uft
= new UnionFindTree
(Collections.
max(graph.
getVertexes())+1); for(Edge e : edges) {
if(!uft.belongsToSameTree(e.u, e.v)) {
uft.unite(e.u, e.v);
result.add(e);
}
}
return result;
}
public static class Graph {
private final Set<Integer> vertexes;
private final List<Edge> edges;
public Graph() {
this.vertexes = new HashSet<Integer>();
this.edges = new ArrayList<Edge>();
}
public Graph(int[][] edges) {
this();
for(int[] e : edges) {
addEdge(e[0], e[1], e[2]);
}
}
public void addEdge(int u, int v, int c) {
vertexes.add(u);
vertexes.add(v);
edges.add(new Edge(u, v, c));
}
public List<Edge> getEdges() {
return new ArrayList<Edge>(edges);
}
public Set<Integer> getVertexes() {
return new HashSet<Integer>(vertexes);
}
}
public static class Edge implements Comparable<Edge> {
public final int u;
public final int v;
public final int c;
public Edge(int u, int v, int c) {
this.u = u;
this.v = v;
this.c = c;
}
@Override
public int compareTo(Edge e) {
return c - e.c;
}
}
private class UnionFindTree {
public UnionFindTree(int n) {
for(int i=0; i<n; i++) {
}
}
public boolean belongsToSameTree(int x, int y) {
return findRootElement(elements[x]).equals(findRootElement(elements[y]));
}
public void unite(int x, int y) {
link(findRootElement(elements[x]), findRootElement(elements[y]));
}
while (!element.isRoot()) {
element = elements[element.parent];
}
return element;
}
if(x.value == y.value) {
return;
}
if(x.rank < y.rank) {
x.parent = y.value;
}
else {
y.parent = x.value;
if(x.rank == y.rank) {
x.rank++;
}
}
}
final int value;
int parent;
int rank;
value = v;
parent = v;
rank = 0;
}
boolean isRoot() {
return parent == value;
}
}
}
}
aW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbnM7CmltcG9ydCBqYXZhLnV0aWwuSGFzaFNldDsKaW1wb3J0IGphdmEudXRpbC5MaXN0OwppbXBvcnQgamF2YS51dGlsLlNldDsKCnB1YmxpYyBjbGFzcyBNYWluIHsKCglwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7CgkJLy8gV2lraXBlZGlh44Gu44K144Oz44OX44Or44Kw44Op44OVCgkJS3J1c2thbC5HcmFwaCBnID0gbmV3IEtydXNrYWwuR3JhcGgoCgkJCW5ldyBpbnRbXVtdewoJCQkJezAsIDEsIDd9LAoJCQkJezAsIDMsIDV9LAoJCQkJezEsIDIsIDh9LAoJCQkJezEsIDMsIDl9LAoJCQkJezEsIDQsIDd9LAoJCQkJezIsIDQsIDV9LAoJCQkJezMsIDQsIDE1fSwKCQkJCXszLCA1LCA2fSwKCQkJCXs0LCA1LCA4fSwKCQkJCXs0LCA2LCA5fSwKCQkJCXs1LCA2LCAxMX0sCgkJCX0KCQkpOwoJCQoJCWludCBjb3N0ID0gMDsKCQlLcnVza2FsIGsgPSBuZXcgS3J1c2thbCgpOwoJCWZvcihLcnVza2FsLkVkZ2UgZSA6IGsuZ2V0TWluaW11bVNwYW5uaW5nVHJlZUVkZ2VzKGcpKSB7CgkJCVN5c3RlbS5vdXQucHJpbnRsbihlLnUgKyAiLCAiICsgZS52ICsgIiwgIiArIGUuYyk7CgkJCWNvc3QgKz0gZS5jOwoJCX0KCQlTeXN0ZW0ub3V0LnByaW50bG4oImNvc3QgOiAiICsgY29zdCk7Cgl9Cn0KCmNsYXNzIEtydXNrYWwgewoKCXB1YmxpYyBMaXN0PEVkZ2U+IGdldE1pbmltdW1TcGFubmluZ1RyZWVFZGdlcyhHcmFwaCBncmFwaCkgewoJCUxpc3Q8RWRnZT4gcmVzdWx0ID0gbmV3IEFycmF5TGlzdDxFZGdlPigpOwoJCUxpc3Q8RWRnZT4gZWRnZXMgPSBncmFwaC5nZXRFZGdlcygpOwoJCUNvbGxlY3Rpb25zLnNvcnQoZWRnZXMpOwoJCVVuaW9uRmluZFRyZWUgdWZ0ID0gbmV3IFVuaW9uRmluZFRyZWUoQ29sbGVjdGlvbnMubWF4KGdyYXBoLmdldFZlcnRleGVzKCkpKzEpOwoJCWZvcihFZGdlIGUgOiBlZGdlcykgewoJCQlpZighdWZ0LmJlbG9uZ3NUb1NhbWVUcmVlKGUudSwgZS52KSkgewoJCQkJdWZ0LnVuaXRlKGUudSwgZS52KTsKCQkJCXJlc3VsdC5hZGQoZSk7CgkJCX0KCQl9CgkJcmV0dXJuIHJlc3VsdDsKCX0KCglwdWJsaWMgc3RhdGljIGNsYXNzIEdyYXBoIHsKCQlwcml2YXRlIGZpbmFsIFNldDxJbnRlZ2VyPiB2ZXJ0ZXhlczsKCQlwcml2YXRlIGZpbmFsIExpc3Q8RWRnZT4gZWRnZXM7CgkJCgkJcHVibGljIEdyYXBoKCkgewoJCQl0aGlzLnZlcnRleGVzID0gbmV3IEhhc2hTZXQ8SW50ZWdlcj4oKTsKCQkJdGhpcy5lZGdlcyA9IG5ldyBBcnJheUxpc3Q8RWRnZT4oKTsKCQl9CgkJCgkJcHVibGljIEdyYXBoKGludFtdW10gZWRnZXMpIHsKCQkJdGhpcygpOwoJCQlmb3IoaW50W10gZSA6IGVkZ2VzKSB7CgkJCQlhZGRFZGdlKGVbMF0sIGVbMV0sIGVbMl0pOwoJCQl9CgkJfQoJCQoJCXB1YmxpYyB2b2lkIGFkZEVkZ2UoaW50IHUsIGludCB2LCBpbnQgYykgewoJCQl2ZXJ0ZXhlcy5hZGQodSk7CgkJCXZlcnRleGVzLmFkZCh2KTsKCQkJZWRnZXMuYWRkKG5ldyBFZGdlKHUsIHYsIGMpKTsKCQl9CgkJCgkJcHVibGljIExpc3Q8RWRnZT4gZ2V0RWRnZXMoKSB7CgkJCXJldHVybiBuZXcgQXJyYXlMaXN0PEVkZ2U+KGVkZ2VzKTsKCQl9CgkJCgkJcHVibGljIFNldDxJbnRlZ2VyPiBnZXRWZXJ0ZXhlcygpIHsKCQkJcmV0dXJuIG5ldyBIYXNoU2V0PEludGVnZXI+KHZlcnRleGVzKTsKCQl9Cgl9CgkKCXB1YmxpYyBzdGF0aWMgY2xhc3MgRWRnZSBpbXBsZW1lbnRzIENvbXBhcmFibGU8RWRnZT4gewoJCXB1YmxpYyBmaW5hbCBpbnQgdTsKCQlwdWJsaWMgZmluYWwgaW50IHY7CgkJcHVibGljIGZpbmFsIGludCBjOwoKCQlwdWJsaWMgRWRnZShpbnQgdSwgaW50IHYsIGludCBjKSB7CgkJCXRoaXMudSA9IHU7CgkJCXRoaXMudiA9IHY7CgkJCXRoaXMuYyA9IGM7CgkJfQoKCQlAT3ZlcnJpZGUKCQlwdWJsaWMgaW50IGNvbXBhcmVUbyhFZGdlIGUpIHsKCQkJcmV0dXJuIGMgLSBlLmM7CgkJfQoJfQoKCXByaXZhdGUgY2xhc3MgVW5pb25GaW5kVHJlZSB7CgkJcHJpdmF0ZSBmaW5hbCBFbGVtZW50W10gZWxlbWVudHM7CgoJCXB1YmxpYyBVbmlvbkZpbmRUcmVlKGludCBuKSB7CgkJCWVsZW1lbnRzID0gbmV3IEVsZW1lbnRbbl07CgkJCWZvcihpbnQgaT0wOyBpPG47IGkrKykgewoJCQkJZWxlbWVudHNbaV0gPSBuZXcgRWxlbWVudChpKTsKCQkJfQoJCX0KCgkJcHVibGljIGJvb2xlYW4gYmVsb25nc1RvU2FtZVRyZWUoaW50IHgsIGludCB5KSB7CgkJCXJldHVybiBmaW5kUm9vdEVsZW1lbnQoZWxlbWVudHNbeF0pLmVxdWFscyhmaW5kUm9vdEVsZW1lbnQoZWxlbWVudHNbeV0pKTsKCQl9CgoJCXB1YmxpYyB2b2lkIHVuaXRlKGludCB4LCBpbnQgeSkgewoJCQlsaW5rKGZpbmRSb290RWxlbWVudChlbGVtZW50c1t4XSksIGZpbmRSb290RWxlbWVudChlbGVtZW50c1t5XSkpOwoJCX0KCgkJcHJpdmF0ZSBFbGVtZW50IGZpbmRSb290RWxlbWVudChFbGVtZW50IHgpIHsKCQkJRWxlbWVudCBlbGVtZW50ID0geDsKCQkJd2hpbGUgKCFlbGVtZW50LmlzUm9vdCgpKSB7CgkJCQllbGVtZW50ID0gZWxlbWVudHNbZWxlbWVudC5wYXJlbnRdOwoJCQl9CgkJCXJldHVybiBlbGVtZW50OwoJCX0KCgkJcHJpdmF0ZSB2b2lkIGxpbmsoRWxlbWVudCB4LCBFbGVtZW50IHkpIHsKCQkJaWYoeC52YWx1ZSA9PSB5LnZhbHVlKSB7CgkJCQlyZXR1cm47CgkJCX0KCQkJaWYoeC5yYW5rIDwgeS5yYW5rKSB7CgkJCQl4LnBhcmVudCA9IHkudmFsdWU7CgkJCX0KCQkJZWxzZSB7CgkJCQl5LnBhcmVudCA9IHgudmFsdWU7CgkJCQlpZih4LnJhbmsgPT0geS5yYW5rKSB7CgkJCQkJeC5yYW5rKys7CgkJCQl9CgkJCX0KCQl9CgoJCXByaXZhdGUgY2xhc3MgRWxlbWVudCB7CgkJCWZpbmFsIGludCB2YWx1ZTsKCQkJaW50IHBhcmVudDsKCQkJaW50IHJhbms7CgoJCQlwcml2YXRlIEVsZW1lbnQoaW50IHYpIHsKCQkJCXZhbHVlID0gdjsKCQkJCXBhcmVudCA9IHY7CgkJCQlyYW5rID0gMDsKCQkJfQoKCQkJYm9vbGVhbiBpc1Jvb3QoKSB7CgkJCQlyZXR1cm4gcGFyZW50ID09IHZhbHVlOwoJCQl9CgkJfQoJfQoKfQo=