import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.PriorityQueue; import java.util.Set; public class test38 { //点的定义 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<>(); } } //形成图结构 //传进来二维数组,每行有三个值,分别为权重,from和to这三个属性代表了每个点的结构 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]; //如果图里没有from这个点,就新建 if (!graph.nodes.containsKey(from)) { graph.nodes.put(from, new Node(from)); } //如果图里没有to这个点,就新建 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 EdgeComparator implements Comparator<Edge> { //根据权值排序,权值小的在左,权值大的在右 public int compare(Edge o1 , Edge o2){ return o1.weight - o2.weight; } } public static Set<Edge> primMST(Graph graph){ //解锁的边进入小根堆 PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(new EdgeComparator()); //哪些点被解锁出来了 HashSet<Node> nodeSet = new HashSet<>(); //已经考虑过的边不要重复考虑 HashSet<Edge> edgeSet = new HashSet<>(); //依次挑选的边在result里 Set<Edge> result = new HashSet<>(); //随便挑一个点,同时也避免了森林的影响 for(Node node : graph.nodes.values()){ //node是开始点 if(!nodeSet.contains(node)){ nodeSet.add(node); for(Edge edge : node.edges){ //如果已经考虑的边没有这个边,那么两个集合都要把这个边加进去 if(!edgeSet.contains(edge)){ edgeSet.add(edge); priorityQueue.add(edge); } //解锁所有相连的边进入小根堆 priorityQueue.add(edge); } // while (!priorityQueue.isEmpty()){ Edge edge = priorityQueue.poll();//弹出最小的边 Node toNode = edge.to;//边的另一端 if(!nodeSet.contains(toNode)){ //边的另一端没有解锁就把它解锁,并且将它加在result集合中 nodeSet.add(toNode); result.add(edge); for (Edge nextEdge : toNode.edges){ if(!edgeSet.contains(nextEdge)){ //如果边的另一端的点(解锁的点)的相邻边没有考虑,那么两个集合都要把这个边加进去 edgeSet.add(nextEdge); priorityQueue.add(nextEdge); } //解锁的点又解锁了一批边进入小根堆 priorityQueue.add(nextEdge); } } } } break; } return result; } }
12-13
4499
08-24
703
12-22
1467
04-15