介绍

克鲁斯卡尔(Kruskal)算法是用来求出连通图中最小生成树的算法。

连通图:指无向图中任意两点都能相通的图。

最小生成树:指联通图的所有生成树中边权重的总和最小的树(即,找出一个树,让其联通所有的点,并让树的边权和为最小)。

算法思想

克鲁斯卡尔算法的主要基本思想有两点原则:

  • 按照从小到大的顺序选择边,并将边的两端连线,构成新的图
  • 保证新加入的边不能在新的图上形成环
  • 重复以上步骤,直至添加n-1条边

    用图表示该算法的解体过程:

算法证明

我是通过反证的方式理解该算法的。

  1. 证明按上述算法添加n-1条边时,一定能连通n个节点。

证明:Kruskal算法保证了针对n个节点,它添加了n-1条边,且不存在环。那么假设这n-1条边没有全部连通n个节点。也就说至少有1个点没有边,那么至多只有n-1个点使用n-1条边,当n-1个点使用n-1条边时,必定构成环。与要求不符,故反正成立。

  1. 证明新的图中再添加一条边,一定构成环。

步骤一证明了新生成的图一定是一个连通图,也就是任意两点之间必定已经相连,当我们在加入一条新的边的时候,边两段的点又多了一条新相连的路,因此构成了环。

  1. 证明在构成新的环中,新加入的边一定是最长的边。

假设新加入的边,并非是环中最大的边,那么可以去掉这个环中最大的边,且剩下的边不够环,这与逐步加入小的边且不构成环这一条件矛盾。因此证明新加入的边一定为最长的边。

算法实现

public class Kruskal {

    public static void generateMinTree(int[][] graph){
if(graph == null || graph.length <=0)
throw new IllegalArgumentException(); int minSum = 0;
//标记哪些点已经到访过
int[][] visited = new int[graph.length][graph.length]; //用来表示父子级的关系,验证是否存在环
int[] nodeHierarchy = new int[graph.length];
for(int i=0; i<nodeHierarchy.length; i++){
nodeHierarchy[i] = i;
} int n = 0;
while(n < graph.length -1){
int minVal = Integer.MAX_VALUE;
int iIndex = 0;
int jIndex = 0; for(int i=0; i<graph.length; i++){
for(int j=i+1; j<graph[i].length; j++){
if(graph[i][j] != Integer.MAX_VALUE && visited[i][j] == 0 && graph[i][j] < minVal){
iIndex = i;
jIndex = j;
minVal = graph[i][j];
}
}
}
visited[iIndex][jIndex] = 1; //判断父节点是否相同,确定是否构成了环
if(findFather(nodeHierarchy, iIndex) != findFather(nodeHierarchy, jIndex)){
System.out.println(n + " Round min value path: " + minVal + " from " + iIndex + " to " + jIndex);
minSum += graph[iIndex][jIndex];
updateHierarchy(nodeHierarchy, iIndex, jIndex);
n++;
}
System.out.println("node hierarchy:" + Arrays.toString(nodeHierarchy)); } System.out.println("min tree path sum:" + minSum);
System.out.println("node hierarchy:" + Arrays.toString(nodeHierarchy)); } //递归查找父节点
private static int findFather(int[] nodeHierarchy, int idx){ if(nodeHierarchy[idx] == idx)
return idx; return findFather(nodeHierarchy, nodeHierarchy[idx]); } //递归更新父节点
private static void updateHierarchy(int[] nodeHierarchy, int from, int to){
if(nodeHierarchy[from] != from)
updateHierarchy(nodeHierarchy, nodeHierarchy[from], from);
nodeHierarchy[from] = to;
} }

上述代码见Github

日日算法:Kruskal算法的更多相关文章

  1. 最小生成树之算法记录【prime算法+Kruskal算法】【模板】

    首先说一下什么是树: 1.只含一个根节点 2.任意两个节点之间只能有一条或者没有线相连 3.任意两个节点之间都可以通过别的节点间接相连 4.除了根节点没一个节点都只有唯一的一个父节点 5.也有可能是空 ...

  2. 最小生成树(prime算法 & kruskal算法)和 最短路径算法(floyd算法 & dijkstra算法)

    一.主要内容: 介绍图论中两大经典问题:最小生成树问题以及最短路径问题,以及给出解决每个问题的两种不同算法. 其中最小生成树问题可参考以下题目: 题目1012:畅通工程 http://ac.jobdu ...

  3. 最小生成树(Prim算法+Kruskal算法)

    什么是最小生成树(MST)? 给定一个带权的无向连通图,选取一棵生成树(原图的极小连通子图),使生成树上所有边上权的总和为最小,称为该图的最小生成树. 求解最小生成树的算法一般有这两种:Prim算法和 ...

  4. [贪心经典算法]Kruskal算法

    Kruskal算法的高效实现需要一种称作并查集的结构.我们在这里不介绍并查集,只介绍Kruskal算法的基本思想和证明,实现留在以后讨论. Kruskal算法的过程: (1) 将全部边按照权值由小到大 ...

  5. hdu 1233 还是畅通工程 最小生成树(prim算法 + kruskal算法)

    还是畅通工程                                                                            Time Limit: 4000/2 ...

  6. 最小生成树 Prim算法 Kruskal算法实现

    最小生成树定义 最小生成树是一副连通加权无向图中一棵权值最小的生成树. 在一给定的无向图 G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即,而 w(u, v) 代表此边的 ...

  7. 最小生成树Prim算法 Kruskal算法

    Prim算法(贪心策略)N^2 选定图中任意定点v0,从v0开始生成最小生成树 树中节点Va,树外节点Vb 最开始选一个点为Va,其余Vb, 之后不断加Vb到Va最短距离的点 1.初始化d[v0]=0 ...

  8. 【431】Prim 算法 & Kruskal 算法

    Prim 算法: Minimum Spanning Tree(MST):最小生成树,就是连接所有节点的最小权值 mst集合与rest集合 mst集合中顶点,找到一条最小权值的边 然后把边相关的顶点,选 ...

  9. 最小生成树Prim算法Kruskal算法

    Prim算法采用与Dijkstra.Bellamn-Ford算法一样的“蓝白点”思想:白点代表已经进入最小生成树的点,蓝点代表未进入最小生成树的点. 算法分析 & 思想讲解: Prim算法每次 ...

  10. 克鲁斯卡尔算法(Kruskal算法)求最小生成树

    题目传送:https://loj.ac/p/10065 1.排序函数sort,任何一种排序算法都行,下面的示例代码中,我采用的是冒泡排序算法 2.寻源函数getRoot,寻找某一个点在并查集中的根,注 ...

随机推荐

  1. Azure多因素认证

    什么是多重身份验证? 双重验证是需要多种验证方法的身份验证方法,可为用户登录和事务额外提供一层重要的安全保障. 它的工作原理是需要以下两种或多种验证方法: 用户知道的某样东西(通常为密码) 用户具有的 ...

  2. 【php】面向对象(二)

    一. 封装: a) 描述:使用成员修饰符修饰成员属性和成员方法,能够最大限度的隐藏对象内部的细节,保证对象的安全 b) PPP修饰符:public(公共的),protected(受保护的),priva ...

  3. 【php】正则表达式

    一.生活当中的正则表达式: a)Notepad++.word等这些具有编辑功能的软件,都具有一个查找.替换的功能,这个功能,其实就属于正则模式的一种匹配.替换:包括windows当中可以实现的查找,也 ...

  4. hive常用函数一

    Hive概念 Hive最适合于数据仓库应用程序,使用该应用程序进行相关静态数据分析,不需要快速响应出结果,而数据本身不会发生频繁变化. Hdfs分布式文件系统限制了hive,使其不支持记录级别的更新. ...

  5. lr具体使用步骤概述

    lr具体使用 1 无工具情况下的性能测试 2性能测试工具LoadRunner的工作原理 3 VuGen应用介绍 4 协议的类型及选择方法 5 脚本的创建过程 6 脚本的参数化 7 调试技术 8 Con ...

  6. 01-启动jmeter目录功能

    1.bin :存储了jmeter的可执行程序,如启动脚本.配置程序 docs:    api扩展文档存放 lib:   lib\ext   存储了jmeter的整合的功能(如.jar文件程序,和第三方 ...

  7. 正则表达式(JS表格简要总结)

    1. JS中正则表达式定义 JavaScript 中的正则表达式用 RegExp 对象表示. JS中定义正则表达式的两种方法: 方法 示例 RegExp 对象 var pattern = new Re ...

  8. AJ学IOS 之BLOCK的妙用_利用block实现链式编程

    AJ分享,必须精品 一:场景 我们有个对象人,他有两个方法,一个是学习study,一个是跑步run, 这个人有个怪癖,跑完步之后必须学习,为了实现这个方法并且能调用方便,我们让跑步和学习都回返回自己这 ...

  9. 使用Jmeter测试java请求

    1.性能测试过程中,有时候开发想对JAVA代码进行性能测试,Jmeter是支持对Java请求进行性能测试,但是需要自己开发.打包好要测试的代码,就能在Java请求中对该java方法进行性能测试2.本文 ...

  10. c++学习day01基础知识学习

    一.代码示例解析: #include <iostream> int main() { using namespace std; cout << "come up an ...