kruskal算法

贪心算法(2)-Kruskal最小生成树

坚强是说给别人听的谎言 提交于 2020-03-19 09:08:21
什么是最小生成树? 生成树是相对图来说的,一个图的生成树是一个树并把图的所有顶点连接在一起。一个图可以有许多不同的生成树。一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。最小生成树其实是 最小权重生成树 的简称。生成树的权重是考虑到了生成树的每条边的权重的总和。 最小生成树有几条边? 最小生成树有(V – 1)条边,其中V是给定的图的顶点数量。 Kruskal算法 下面是步骤寻找MST使用Kruskal算法 1 1,按照所有边的权重排序(从小到大) 2 3 2,选择最小的边。检查它是否形成与当前生成树形成环。如果没有形成环,讲这条边加入生成树。否则,丢弃它。 4 5 3,重复第2步,直到有生成树(V-1)条边 步骤2使用 并查集算法 来检测环。如果不熟悉并查集建议阅读下 并查集 。 该算法是一种贪心算法。贪心的选择是选择最小的权重的边,并不会和当前的生成树形成环。让我们了解一个例子,考虑下面输入图 spanning-tree-mst 该图包含9个顶点和14个边。因此,形成最小生成树将有(9 – 1)= 8条边。 01 排序后: 02 Weight Src Dest 03 1 7 6 04 2 8 2 05 2 6 5 06 4 0 1 07 4 2 5 08 6 8 6 09 7 2 3 10 7 7 8 11 8

最小生成树算法——kruskal

风流意气都作罢 提交于 2020-03-08 16:38:35
如图,输出最小生成树的生成过程 算法思想: 每个边的权值进行从小到大排序 然后从小到大添加到最小生成树中,若添加一个边后构成环路,则此边不能添加。直到每个顶点都加入到最小生成树中。 需要一个结构体来存储 每个边的权值与始末顶点。再进行排序。 struct { VexType head ; VexType tail ; ArcType lowcost ; } Edge [ MAXSIZE ] ; //存入每条边的首尾以及权值 通过无向图写出邻接矩阵,调用函数创建邻接矩阵 VexType vexs [ 7 ] = { '0' , '1' , '2' , '3' , '4' , '5' , '6' } ; ArcType arcs [ 7 ] [ 7 ] = { { 0 , 17 , MAXNUM , MAXNUM , MAXNUM , 10 , MAXNUM } , { 17 , 0 , 16 , MAXNUM , MAXNUM , MAXNUM , 14 } , { MAXNUM , 16 , 0 , 12 , MAXNUM , MAXNUM , MAXNUM } , { MAXNUM , MAXNUM , 12 , 0 , 19 , MAXNUM , 18 } , { MAXNUM , MAXNUM , MAXNUM , 19 , 0 , 25 , 24 } , { 10 ,

Kruskal算法构造最小生成树

孤人 提交于 2020-03-01 01:25:32
问题[描述算法问题,首选形式化方式(数学语言),其次才是非形式化方式(日常语言)] 在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无向循环图,使得的 sum(w(u, v))最小,则此 T 为 G 的最小生成树。 解析[问题的理解和推导,可用电子版直接在此编写,也可用纸笔推导,拍照嵌入本文档] 设计[核心伪代码] 首先运用快排把边按升序分别排列好,然后再开始KRUSKAL函数 void kruskal(Edge E[],int n,int e){ 定义一个初始数组 k表示当前最小生成树边的总数 j表示E里边的下标,默认初值为0 当生成的边数小于总边长的时候继续循环 { m1=E[j].vex1; m2=E[j].vex2;//取一条边的两个邻接点 sn1=vset[m1]; sn2=vset[m2]; //分别得到两个顶点所属的集合编号 if(sn1!=sn2)//两顶点分属于不同的集合,该边是最小生成树的一条边 { 输出两个顶点和所在边 总和相加 生成的最小生成树边数增加1 如果边有达到最大的数量 退出循环 for(i=1;i<=n;i++) 两个集合统一起来集合编号修改 } 继续下一条边 } 最后输出总和} 4. 分析[算法复杂度推导]时间复杂度

(最小生成树)Kruskal算法

拈花ヽ惹草 提交于 2020-02-14 00:11:55
            (最小生成树)Kruskal算法     Kruskal算法的高效实现需要一种称作并查集的结构。。   Kruskal算法的过程:   (1) 将全部边按照权值由小到大排序。   (2) 按顺序(边权由小到大的顺序)考虑每条边,只要这条边和我们已经选择的边不构成圈,就保留这条边,否则放弃这条边。    算法 成功选择(n-1)条边后,形成一棵最小生成树,当然如果算法无法选择出(n-1)条边,则说明原图不连通。   算法要点:Kruskal算法的最难点在于怎样判断加入边(x, y)后是否形成了环.   问题可化简为:判断边(x, y)的两个顶点在图(实际是森林)mst中是否已连通。如果已经连通,加入边将形成环;   否则,不形成环。   Kruskal算法中, 要用到并查集的合并与查找。   完整代码如下:(具体见代码注释) 1 #include<bits/stdc++.h> 2 #define ll long long 3 4 using namespace std; 5 int n, m, ans = 0, tmp = 1; 6 int fa[1000100]; 7 int getfa(int x){ 8 if(x == fa[x]) return x; 9 else return fa[x] = getfa(fa[x]); 10 } 11 struct

【最小生成树之Kruskal算法】

我的未来我决定 提交于 2020-02-13 14:10:20
看完之后推荐再看一看 【最小生成树之Prim算法】-C++ 定义 :一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。最小生成树可以用kruskal(克鲁斯卡尔)算法或Prim(普里姆)算法求出。 。 ​在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得 的 w(T) 最小,则此 T 为 G 的最小生成树。 最小生成树其实是最小权重生成树的简称。 许多应用问题都是一个求无向连通图的最小生成树问题。例如:要在n个城市之间铺设光缆,主要目标是要使这 n 个城市的任意两个之间都可以通信,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同;另一个目标是要使铺设光缆的总费用最低。这就需要找到带权的最小生成树。 这一章主要介绍Kruskal算法。 Kruskal算法的 时间复杂度 :O(m*log(n))(点数n边数m) 主要思路: 输入之后对边权值进行排序,然后按边权值从小到大进行合并(merge)操作,如果操作成功(被合并的两个点不在一棵树上),则把这两个顶点的边权值加入总数,最后输出total即可。 主要使用: “并查集。” 洛谷P3366【模板】最小生成树

最小生成树的Kruskal算法

自闭症网瘾萝莉.ら 提交于 2020-02-13 13:54:54
库鲁斯卡尔(Kruskal)算法是一种按照连通网中边的权值递增的顺序构造最小生成树的方法。Kruskal算法的基本思想是:假设连通网G=(V,E),令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),图中每个顶点自成一个连通分量。在E中选择权值最小的边,若该边依附的顶点落在T中不同的连通分量中,则将此边加入到T中;否则,舍去此边而选下一条权值最小的边;依次类推,直到T中所有顶点都在同一个连通分量上(此时含有n-1边)为止,这时的T就是一棵最小的生成树。 注意,初始时T的连通分量为顶点个数n,在每一次选取最小权值的边加入到T时一定要保证T的连通分量减1;也即选取最小权值边所连接的两个顶点必须位于不同的连接分量上,否则应舍去此边而再选取下一条最小权值的边。 概述 实现Kruskal算法的关键是如何判断所选取的边是否与生成树中已保留的边形成回路,这可通过判断边的两个顶点所在的连通分量的方法来解决.为此设置一个辅助数组vest(数组元素下标为0~n-1),它用于判断两个顶点集合(即两个连通分量),此时按其中的一个集合编号重新统一编号(即合并成一个连通分量)。因此,当两个顶点的集合(连通分量)编号不同时,则加入这两个顶点所构成的边到最小生成树中就一定不会形成回路,因为这两个顶点分属于不同的连通分量。 在实现Kruskal算法时,需要用一个数组E来存放图G中是所有边

Truck History(建图+最小生成树)

大憨熊 提交于 2020-02-07 04:53:46
** Truck History(建图+最小生成树)** 先摆题 题目巨难读,可能是我英语太菜了吧。。 大意是这样的,给你n个七位字符串,两个字符串的距离就是不同的字母个数,字符串可以变形,每次改变一个字符,问如何能够用最少的操作让一个字符串挨个变成其他字符串的样子。答案输出1/操作次数。 多个输入,0截止。 题目一看,整活最小生成树,那么问题来了,怎么生成? 最小生成树有两种做法,一种是加边法()Kruskal算法),一种是加点法(Prim算法)。 https://blog.csdn.net/a2392008643/article/details/81781766 我是看这篇博客学的,这个东西不难,看懂思路自己就能写了,Kruskal算法需要并查集的基础。 在我学了最小生成树后做的第一道题是用加边法做的,然后,默默地看了一眼数据,加边法必tle,于是 这是一个错误的示范,大家不必细看。。 # include <iostream> # include <algorithm> # include <vector> # include <cstring> using namespace std ; struct node { int l , r , w ; bool operator < ( const node & a ) const { return w < a . w ; } }

求最小生成树-Prim算法和Kruskal算法解析及代码实现

限于喜欢 提交于 2020-02-04 00:19:29
由于数据结构学过一段时间了,有些知识点有点遗忘,所以先来复习一下一些知识点: 什么是最小生成树? 最小生成树是在一个给定的 无向图 G中求一棵树T,使得这棵树拥有图G中的所有顶点,且所有边都是来自图G中的边,并且满足整棵树的边权之和最小。 最小生成树的三个性质: 1,最小生成树是树,因此其边数等于顶点数减1,且树内一定不会有环。 2,对于给定的图G,其最小生成树可以不唯一,但其边权之和一定是唯一的 3,由于最小生成树是在无向图上生成的,因此其根结点可以实这棵树上的任意一个结点。 求最小生成树一般有两种算法,即prim和kruskal。这两种算法都是采用了贪心的思想,只是贪心的策略不太一样。 Prim算法:(普里姆算法) 用来解决最小生成树问题,其基本思想是对图G(V,E)设置集合S,存放已被访问的顶点,然后每次从集合V-S中选择与集合S的最短距离最小的一个顶点(记为 u),访问并加入集合S。之后,令顶点u为中介点,优化所有从u能到达的顶点v 与集合S之间的最短距离。这样的操作执行n次(n为顶点个数),直到集合S已包含所有的顶点。可以发现,prim算法的思想与最短路径中的Dijkstra算法的思想几乎完全相同,只是在涉及最短距离时使用了集合S代替Dijkstra算法中的起点s。 Kruskal算法:(克鲁斯卡尔算法) 同样是用来解决最小生成树问题的一个算法。和prim算法不同

最小生成树-Prim算法和Kruskal算法

*爱你&永不变心* 提交于 2020-01-16 14:36:26
Prim算法 1.概览 普里姆算法 ( Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有 顶点 ( 英语 : Vertex (graph theory)),且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家 沃伊捷赫·亚尔尼克 ( 英语 : Vojtěch Jarník)发现;并在1957年由美国计算机科学家 罗伯特·普里姆 ( 英语 : Robert C. Prim)独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法、亚尔尼克算法或普里姆-亚尔尼克算法。 2.算法简单描述 1).输入:一个加权连通图,其中顶点集合为V,边集合为E; 2).初始化:V new = {x},其中x为集合V中的任一节点(起始点),E new = {},为空; 3).重复下列操作,直到V new = V: a.在集合E中选取权值最小的边<u, v>,其中u为集合V new 中的元素,而v不在V new 集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一); b.将v加入集合V new 中,将<u, v>边加入集合E new 中; 4).输出:使用集合V new 和E new 来描述所得到的最小生成树。 下面对算法的图例描述

算法导论——最小生成树:Kruskal算法(利用了并查集)

醉酒当歌 提交于 2020-01-07 15:11:19
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> package org.loda.graph; import org.loda.structure.MinQ; import org.loda.structure.Queue; import org.loda.util.In; /** * * @ClassName: KruskalMST * @Description:Kruskal最小生成树算法 * @author minjun * @date 2015年5月25日 下午10:50:01 * */ public class KruskalMST { private Queue<Edge> mst; private double weight; public KruskalMST(WeightGraph g){ int v=g.v(); mst=new Queue<Edge>(); MinQ<Edge> q=new MinQ<Edge>(); UF uf=new UF(v); //将所有边添加到优先队列中 for(Edge edge:g.edges()){ q.offer(edge); } while(!q.isEmpty()){ Edge edge=q.poll(); int a=edge.oneSide(); int b=edge.otherSide(a);