最小生成树(Minimum Spanning Tree)的原理及实现(Java)
最小生成树(Minimum Spanning Tree):给定无向图中,边权重最小的生成树。
满足条件
生成树——包含图中所有顶点的树;
最小——边权重之和最小的生成树。
它是图中全局的概念,而SPT(Shortest Path Tree,最短路径树)是相对图中某一个初始节点而言的。
算法原理
Cut和Crossing edge
Cut——将图中所有顶点分入(这个好像是随便来的?)两个非空集合中;
Crossing Edge——连接的顶点分别位于不同的集合中。
在一次cut中,所有crossing edge权值最小的edge一定是MST中的一个边(证明过程很有趣)
Prims算法
1.随机选定graph中的一个顶点;
2.将它和graph中其他顶点分割为两个集合A和B;
3.在Crossing edge中找到权重最小(如果有多个,随便选一个)的edge连接的顶点;
4.重新分割,将3中发现的属于集合B的顶点归入A中;
重复3和4步骤,直至找到MST。步骤三的时间复杂度比较高,可以使用PQ进行优化,不过好难看懂,可以参考这个video。
Kruskals算法
1.将所有edge按照权重在PQ中按从小到大的顺序跟踪;
2.取出PQ跟踪的第一个edge,将其放入MST中,检查是否会形成环路,如果是,则丢弃该edge;
3.重复步骤2直至找到MST(V-1条边)。
java代码
使用如下所示的无向、有权图作为示例
MSTFind.java
import java.util.*;public class MSTFind {private Graph graph;private WQU t;MSTFind(Graph graph) {this.graph = graph;}public List<Graph.Edge> Prims() {/* 1.随机选定graph中的一个顶点;2.将它和graph中其他顶点分割为两个集合A和B;3.在Crossing edge中找到权重最小(如果有多个,随便选一个)的edge连接的顶点,将该edge归入MST中;4.重新分割,将3中发现的属于集合B的顶点归入A中;重复3和4步骤,直至找到MST(V-1条边)。*/Set<Integer> A = new HashSet<>();Set<Integer> B = new HashSet<>();List<Graph.Edge> MST = new ArrayList<>();A.add(0);for (int i = 0; i < graph.V(); i++) {if (!A.contains(i)) {B.add(i);}}while (MST.size() != graph.V() - 1) {Graph.Edge minEdge = findMinCrossEdge(A, B);MST.add(minEdge);cutSets(A, B, minEdge);}return MST;}private Graph.Edge findMinCrossEdge(Set<Integer> a, Set<Integer> b) {/* 找到权重最小的crossing edge*/Graph.Edge res = new Graph.Edge(0, new Graph.Pair(0, Integer.MAX_VALUE));for (int v : a) {for (Graph.Pair p : graph.adj(v)) {if (!a.contains(p.getAnotherV())) {if (p.getWeight() < res.getWeight()) {res = new Graph.Edge(v, p);}}}}return res;}private void cutSets(Set<Integer> a, Set<Integer> b, Graph.Edge e) {for (int v : e.getVs()) {if (!a.contains(v)) {a.add(v);b.remove(v);}}}public List<Graph.Edge> Kruskals() {/* 1.将所有edge按照权重在PQ中按从小到大的顺序跟踪;2.取出PQ跟踪的第一个edge,将其放入MST中,检查是否会形成环路,如果是,则丢弃该edge;3.重复步骤2直至找到MST(V-1条边)。*/PriorityQueue<Graph.Edge> PQ = new PriorityQueue<>(new selfComparator());PQ.addAll(graph.getEdges());t = new WQU(graph.V());List<Graph.Edge> MST = new ArrayList<>();while (MST.size() != graph.V() - 1) {Graph.Edge curEdge = PQ.remove();MST.add(curEdge);if (checkCircle(curEdge)) {MST.remove(MST.size() - 1);}}return MST;}private boolean checkCircle(Graph.Edge e) {/* 使用WQU检测是否存在环路*/int v = e.getV();int w = e.getT().getAnotherV();if (t.isConnected(v, w)) {return true;} else {t.connect(v, w);return false;}}public class selfComparator implements Comparator<Graph.Edge> {@Overridepublic int compare(Graph.Edge o1, Graph.Edge o2) {if (o1.getWeight() < o2.getWeight()) {return -1;} else if (o1.getWeight() > o2.getWeight()) {return 1;}return 0;}}public static void main(String[] args) {Graph test = new Graph(7); // 按照实例初始化graphtest.addEdge(0, 1, 2);test.addEdge(0, 2, 1);test.addEdge(1, 2, 5);test.addEdge(1, 3, 11);test.addEdge(1, 4, 3);test.addEdge(2, 4, 1);test.addEdge(2, 5, 15);test.addEdge(3, 4, 2);test.addEdge(4, 5, 4);test.addEdge(3, 6, 1);test.addEdge(4, 6, 5);test.addEdge(5, 6, 1);MSTFind t = new MSTFind(test);System.out.println("Prims算法的MST:");for (Graph.Edge e : t.Prims()) {System.out.print(e.getVs() + " ");}System.out.println("\nKruskals算法的MST:");for (Graph.Edge e : t.Kruskals()) {System.out.print(e.getVs() + " ");}}
}
Graph.java
import java.util.*;public class Graph {/* 无向、有权图*/private static List<Pair>[] ver;private static Set<Edge> edges;Graph(int v) {/* Create empty graph with v vertices*/ver = new List[v];edges = new HashSet<>();}public static class Pair {private int anotherV;private int weight;Pair(int v, int weight) {this.anotherV = v;this.weight = weight;}public int getAnotherV() {return anotherV;}public int getWeight() {return weight;}}public static class Edge {private int v;private Pair t;Edge(int v, Pair t) {this.v = v;this.t = t;}public int getV() {return v;}public int getWeight() {return t.getWeight();}public List<Integer> getVs() {List<Integer> res = new ArrayList<>();res.add(v);res.add(t.getAnotherV());return res;}}public void addEdge(int v, int w, int weight) {/* add an edge v-w with weight*/Pair pairV = new Pair(w, weight);Pair pairW = new Pair(v, weight);if (ver[v] == null) {ver[v] = new ArrayList<>();}if (ver[w] == null) {ver[w] = new ArrayList<>();}ver[v].add(pairV);ver[w].add(pairW);}Iterable<Pair> adj(int v) {/* vertices adjacent to v*/return ver[v];}public int V() {/* number of vertices*/return ver.length;}public int E() {/* number of edges*/int res = 0;for (int i = 0; i < ver.length; i++) {res += ver[i].size();}return res / 2;}public static void main(String[] args) {Graph test = new Graph(7); // 按照实例初始化graphtest.addEdge(0, 1, 2);test.addEdge(0, 2, 1);test.addEdge(1, 2, 5);test.addEdge(1, 3, 11);test.addEdge(1, 4, 3);test.addEdge(2, 4, 1);test.addEdge(2, 5, 15);test.addEdge(3, 4, 2);test.addEdge(4, 5, 4);test.addEdge(3, 6, 1);test.addEdge(4, 6, 5);test.addEdge(5, 6, 1);for (int i = 0; i < test.V(); i++) {List<Integer> adj = new ArrayList<>();for (Pair p : test.adj(i)) {adj.add(p.getAnotherV());}System.out.println("和" + i + "邻接的顶点为:" + adj);}System.out.println("顶点的数量:" + test.V()); // 顶点的数量应该为5System.out.println("边的的数量:" + test.E()); // 边的数量应该为6}
}
Kruskals算法中检测环路的算法参考Graph中环路检测(DFS&WQU)及实现(Java)
WQU的实现参考加权快速联合(Weighted Quick Union)算法原理及实现(Java)
To be a sailor of the world bound for all ports.
最小生成树(Minimum Spanning Tree)的原理及实现(Java)相关推荐
- 第十三章 ALDS1_12_A:Minimum Spanning Tree 最小生成树
知识点 树是没有环的图 在树中,任意顶点r和顶点v之间必然存在着1条路径 生成树:拥有图G的所有顶点,并且在保证自身是树的前提下拥有尽量多的边. 最小生成树(MST):个边权值总和最小的生成树 普里姆 ...
- Minimum spanning tree HDU - 6954
Minimum spanning tree HDU - 6954 题意: 给定n-1个点,编号从2到n,两点a和b之间的边权重为lcm(a,b).请找出它们形成的最小生成树. 2<=n<= ...
- Directed Minimum Spanning Tree: Chu-Liu/Edmonds Algorithm
我们的现代数据库大作业要求实现一个图查询系统,包括基于属性的子图查询.可达性查询(可选).最短路径查询(可选).TopK最短路径查询(可选).图形化展示(可选)等功能.分成子图同构查询小组以及可达性及 ...
- 《Boost》Part1 Minimum Spanning Tree
<Boost>Part1 Minimum Spanning Tree 1.Boost中的最小生成树介绍 MST最小生成树,是图论中的基本算法,还有一种是最大生成树,此处暂不介绍. 最小生成 ...
- CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)
题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...
- 最小生成树(MST,minimum spanning tree)
生成树:由图生成的树,由图转化为树,进一步可用对树的相关操作来对图进行操作.最小指的是权值最小: 生成树是边的集合,如下图所示的最小生成树:MST={{a,b},{a,f},{f,c}}\text{M ...
- HDU 4408 Minimum Spanning Tree 最小生成树计数
http://acm.hdu.edu.cn/showproblem.php?pid=4408 题意:求最小生成树个数 题解:对于Kruskal算法,我们发现,最小生成树要想用多种方法就要有长度相同的边 ...
- 最小生成树(Minimum Spanning Tree)与最小树形图(Minimum Arborescence)问题
没整理完 生成树:给图中指定一个特殊的点root,选择图中部分已有边生成一棵以root为根的生成树T. 最小生成树:在无向图中生成一棵树,含有的边的总权值要求是所有可能生成树中最小的,该树不唯一. 最 ...
- HDU 4408 - Minimum Spanning Tree(最小生成树计数)
有边权的最小生成树计数 模板 #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostre ...
- 百度之星2018资格赛t6三原色图(MST minimum spanning tree)
ac代码: #include<bits/stdc++.h> #define per(i,a,b) for(int i=a;i<=b;i++) using namespace std; ...
最新文章
- 云计算机基地有辐射吗,服务器机房有辐射大吗
- python学习第一章要点
- iOS无法引入头文件
- python 数据分析学什么-如何在业余时学数据分析?
- 11.2运行异常和编译异常
- pip install transformers出现拒绝访问
- 百度希壤元宇宙平台上线首个汽车数字展厅 领克探索汽车营销新方式
- 采用集成的Windows验证和使用Sql Server身份验证进行数据库的登录
- java main方法调用非静态方法_java中main函数怎么调用外部非static方法
- 汇编语言 利用ASCII以及AND OR进行字符串大小写转换
- python爬虫xpath提取数据_python爬虫三大解析库之XPath解析库通俗易懂详讲
- oracle unpivot 空值,sql – 处理UNPIVOT中的NULL值
- 八数码问题I-bfs和map标记
- AS3图像抖动效果源码。
- 叮叮叮 重点之中的python必备英语单词(2)来啦!请记得查收
- ThinkPHP文件目录说明
- 为什么要发明面向对象编程?
- http请求被挂起 cancled 原因
- Oracle远程服务端配置
- Spark系列(三)SparkContext分析
热门文章
- JVM调优前置知识-深堆Retained Heap和浅堆Shallow Heap
- 在useEffect中使用了setState,报错
- 如何让老用户帮你“裂变”新用户
- html行内设置样式,Js获取/设置行内样式和非行内样式
- WEB前端代码:边框阴影、边框图片、背景样式、文本样式、字体样式
- java中isolate时间_Dart异步编程:Isolate和事件循环
- HTML中设置td的字体颜色
- 【算法】leetcode887鸡蛋掉落题之方法二解析
- 关于使用实验室服务器的GPU以及跑上TensorFlow代码
- Android源码层修改默认时区