You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
2.4 KiB
102 lines
2.4 KiB
package class16;
|
|
|
|
import java.util.Collection;
|
|
import java.util.Comparator;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.PriorityQueue;
|
|
import java.util.Set;
|
|
import java.util.Stack;
|
|
|
|
//undirected graph only
|
|
public class Code04_Kruskal {
|
|
|
|
// Union-Find Set
|
|
public static class UnionFind {
|
|
// key 某一个节点, value key节点往上的节点
|
|
private HashMap<Node, Node> fatherMap;
|
|
// key 某一个集合的代表节点, value key所在集合的节点个数
|
|
private HashMap<Node, Integer> sizeMap;
|
|
|
|
public UnionFind() {
|
|
fatherMap = new HashMap<Node, Node>();
|
|
sizeMap = new HashMap<Node, Integer>();
|
|
}
|
|
|
|
public void makeSets(Collection<Node> nodes) {
|
|
fatherMap.clear();
|
|
sizeMap.clear();
|
|
for (Node node : nodes) {
|
|
fatherMap.put(node, node);
|
|
sizeMap.put(node, 1);
|
|
}
|
|
}
|
|
|
|
private Node findFather(Node n) {
|
|
Stack<Node> path = new Stack<>();
|
|
while(n != fatherMap.get(n)) {
|
|
path.add(n);
|
|
n = fatherMap.get(n);
|
|
}
|
|
while(!path.isEmpty()) {
|
|
fatherMap.put(path.pop(), n);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
public boolean isSameSet(Node a, Node b) {
|
|
return findFather(a) == findFather(b);
|
|
}
|
|
|
|
public void union(Node a, Node b) {
|
|
if (a == null || b == null) {
|
|
return;
|
|
}
|
|
Node aDai = findFather(a);
|
|
Node bDai = findFather(b);
|
|
if (aDai != bDai) {
|
|
int aSetSize = sizeMap.get(aDai);
|
|
int bSetSize = sizeMap.get(bDai);
|
|
if (aSetSize <= bSetSize) {
|
|
fatherMap.put(aDai, bDai);
|
|
sizeMap.put(bDai, aSetSize + bSetSize);
|
|
sizeMap.remove(aDai);
|
|
} else {
|
|
fatherMap.put(bDai, aDai);
|
|
sizeMap.put(aDai, aSetSize + bSetSize);
|
|
sizeMap.remove(bDai);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public static class EdgeComparator implements Comparator<Edge> {
|
|
|
|
@Override
|
|
public int compare(Edge o1, Edge o2) {
|
|
return o1.weight - o2.weight;
|
|
}
|
|
|
|
}
|
|
|
|
public static Set<Edge> kruskalMST(Graph graph) {
|
|
UnionFind unionFind = new UnionFind();
|
|
unionFind.makeSets(graph.nodes.values());
|
|
// 从小的边到大的边,依次弹出,小根堆!
|
|
PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(new EdgeComparator());
|
|
for (Edge edge : graph.edges) { // M 条边
|
|
priorityQueue.add(edge); // O(logM)
|
|
}
|
|
Set<Edge> result = new HashSet<>();
|
|
while (!priorityQueue.isEmpty()) { // M 条边
|
|
Edge edge = priorityQueue.poll(); // O(logM)
|
|
if (!unionFind.isSameSet(edge.from, edge.to)) { // O(1)
|
|
result.add(edge);
|
|
unionFind.union(edge.from, edge.to);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
}
|