import java.util.ArrayList;
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;
public class test37 {
// 定义节点类
public static class Node {
public int value; // 节点的值
public int in; // 入度
public int out; // 出度
public ArrayList<Node> nexts; // 邻接表,存储与该节点相连的其他节点
public ArrayList<Edge> edges; // 存储从该节点出发的边
public Node(int value) {
this.value = value;
in = 0;
out = 0;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}
}
// 定义边类
public static class Edge {
public int weight; // 边的权重
public Node from; // 起始节点
public Node to; // 终止节点
public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}
}
// 定义图类
public static class Graph {
public HashMap<Integer, Node> nodes; // 存储图中的所有节点,键为节点值,值为节点对象
public HashSet<Edge> edges; // 存储图中的所有边
public Graph() {
nodes = new HashMap<>();
edges = new HashSet<>();
}
}
// 根据给定的矩阵创建图
public static Graph createGraph(Integer[][] matrix) {
Graph graph = new Graph();
for (int i = 0; i < matrix.length; i++) {
Integer weight = matrix[i][0]; // 边的权重
Integer from = matrix[i][1]; // 起始节点的值
Integer to = matrix[i][2]; // 终止节点的值
// 如果图中不存在起始节点,则添加该节点
if (!graph.nodes.containsKey(from)) {
graph.nodes.put(from, new Node(from));
}
// 如果图中不存在终止节点,则添加该节点
if (!graph.nodes.containsKey(to)) {
graph.nodes.put(to, new Node(to));
}
// 获取起始节点和终止节点的对象
Node fromNode = graph.nodes.get(from);
Node toNode = graph.nodes.get(to);
// 创建一条新的边并添加到图中
Edge newEdge = new Edge(weight, fromNode, toNode);
// 更新节点的邻接表和度数信息
fromNode.nexts.add(toNode);
fromNode.out++;
toNode.in++;
fromNode.edges.add(newEdge);
graph.edges.add(newEdge);
}
return graph;
}
// 定义并查集类
public static class UnionFind{
private HashMap<Node , Node> fatherMap; // 存储每个节点的父节点
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>{
// 根据权值排序,权值小的在左,权值大的在右
public int compare(Edge o1 , Edge o2){
return o1.weight - o2.weight;
}
}
// Kruskal算法求最小生成树
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){
priorityQueue.add(edge);
}
Set<Edge> result = new HashSet<>();
while (!priorityQueue.isEmpty()){
Edge edge = priorityQueue.poll();
if(!unionFind.isSameSet(edge.from , edge.to)){
result.add(edge);
unionFind.union(edge.from , edge.to);
}
}
return result;
}
}