最小生成树(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)相关推荐

  1. 第十三章 ALDS1_12_A:Minimum Spanning Tree 最小生成树

    知识点 树是没有环的图 在树中,任意顶点r和顶点v之间必然存在着1条路径 生成树:拥有图G的所有顶点,并且在保证自身是树的前提下拥有尽量多的边. 最小生成树(MST):个边权值总和最小的生成树 普里姆 ...

  2. Minimum spanning tree HDU - 6954

    Minimum spanning tree HDU - 6954 题意: 给定n-1个点,编号从2到n,两点a和b之间的边权重为lcm(a,b).请找出它们形成的最小生成树. 2<=n<= ...

  3. Directed Minimum Spanning Tree: Chu-Liu/Edmonds Algorithm

    我们的现代数据库大作业要求实现一个图查询系统,包括基于属性的子图查询.可达性查询(可选).最短路径查询(可选).TopK最短路径查询(可选).图形化展示(可选)等功能.分成子图同构查询小组以及可达性及 ...

  4. 《Boost》Part1 Minimum Spanning Tree

    <Boost>Part1 Minimum Spanning Tree 1.Boost中的最小生成树介绍 MST最小生成树,是图论中的基本算法,还有一种是最大生成树,此处暂不介绍. 最小生成 ...

  5. CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)

    题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...

  6. 最小生成树(MST,minimum spanning tree)

    生成树:由图生成的树,由图转化为树,进一步可用对树的相关操作来对图进行操作.最小指的是权值最小: 生成树是边的集合,如下图所示的最小生成树:MST={{a,b},{a,f},{f,c}}\text{M ...

  7. HDU 4408 Minimum Spanning Tree 最小生成树计数

    http://acm.hdu.edu.cn/showproblem.php?pid=4408 题意:求最小生成树个数 题解:对于Kruskal算法,我们发现,最小生成树要想用多种方法就要有长度相同的边 ...

  8. 最小生成树(Minimum Spanning Tree)与最小树形图(Minimum Arborescence)问题

    没整理完 生成树:给图中指定一个特殊的点root,选择图中部分已有边生成一棵以root为根的生成树T. 最小生成树:在无向图中生成一棵树,含有的边的总权值要求是所有可能生成树中最小的,该树不唯一. 最 ...

  9. HDU 4408 - Minimum Spanning Tree(最小生成树计数)

    有边权的最小生成树计数 模板 #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostre ...

  10. 百度之星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; ...

最新文章

  1. 云计算机基地有辐射吗,服务器机房有辐射大吗
  2. python学习第一章要点
  3. iOS无法引入头文件
  4. python 数据分析学什么-如何在业余时学数据分析?
  5. 11.2运行异常和编译异常
  6. pip install transformers出现拒绝访问
  7. 百度希壤元宇宙平台上线首个汽车数字展厅 领克探索汽车营销新方式
  8. 采用集成的Windows验证和使用Sql Server身份验证进行数据库的登录
  9. java main方法调用非静态方法_java中main函数怎么调用外部非static方法
  10. 汇编语言 利用ASCII以及AND OR进行字符串大小写转换
  11. python爬虫xpath提取数据_python爬虫三大解析库之XPath解析库通俗易懂详讲
  12. oracle unpivot 空值,sql – 处理UNPIVOT中的NULL值
  13. 八数码问题I-bfs和map标记
  14. AS3图像抖动效果源码。
  15. 叮叮叮 重点之中的python必备英语单词(2)来啦!请记得查收
  16. ThinkPHP文件目录说明
  17. 为什么要发明面向对象编程?
  18. http请求被挂起 cancled 原因
  19. Oracle远程服务端配置
  20. Spark系列(三)SparkContext分析

热门文章

  1. JVM调优前置知识-深堆Retained Heap和浅堆Shallow Heap
  2. 在useEffect中使用了setState,报错
  3. 如何让老用户帮你“裂变”新用户
  4. html行内设置样式,Js获取/设置行内样式和非行内样式
  5. WEB前端代码:边框阴影、边框图片、背景样式、文本样式、字体样式
  6. java中isolate时间_Dart异步编程:Isolate和事件循环
  7. HTML中设置td的字体颜色
  8. 【算法】leetcode887鸡蛋掉落题之方法二解析
  9. 关于使用实验室服务器的GPU以及跑上TensorFlow代码
  10. Android源码层修改默认时区