最小生成树

最小生成树问题(下)

做~自己de王妃 提交于 2020-02-15 05:31:42
克鲁斯卡尔算法 简述 代码及注释 简述 这种算法是求最短的合法n-1条边,用到了并查集,来避免环的产生。 代码及注释 # include <iostream> # include <algorithm> # define M 0x3f3f3f3f using namespace std ; struct Node { //创建一个结构体数组 存点的位置和权值 int x , y , value ; Node ( ) { value = M ; } //将所有点权值设为无穷大 表示到不了 } ; int n , m , v [ 101 ] = { 0 } , f [ 101 ] ; //一个标记是否访问 一个家族谱数组 int ans = 0 ; Node q [ 1010 ] ; int cmp ( Node x , Node y ) { return x . value < y . value ; } void init ( ) { cin >> n ; for ( int i = 1 ; i <= n ; i ++ ) { for ( int j = 1 ; j <= n ; j ++ ) { int a ; //中间量 cin >> a ; //输入i到j的权值大小 if ( j < i ) { //矩阵只输入下半个直角三角形(前提无向图) if ( a != 0 ) { /

生成树及最小生成树

 ̄綄美尐妖づ 提交于 2020-02-15 03:18:43
1. 生成树   一个连通图的生成树是一个极小连通子图,它包含图中的全部顶点,但只有构成一棵树的n-1条边。   对于有n个顶点的连通图,至少有n-1条边,而生成树中恰好有n-1条边,所以连通图的生成树是该图的极小连通子图。若在图的生成树中任意加一条边,则必然形成回路。 2. 最小生成树   对于连通网来说,边是带权值的,生成树的各边也带权值,因此把生成树各边的权值总和称为生成树的权,把权值最小的生成树称为最小生成树。   a. 普里姆算法 → → → → → →   b. 克鲁斯卡尔算法 来源: https://www.cnblogs.com/ImaY/p/4367688.html

生成树与最小生成树

半城伤御伤魂 提交于 2020-02-15 03:12:33
生成树 生成树是 对图遍历访问的一条无回路的遍历路径称为图的生成树,生成树不是唯一的,深度优先和广度优先的访问路径就是一棵生成树.深度优先搜索与广度优先搜索的生成树分别称为***, 最小生成树 最小生成树是对带有权值的图,生成树路径中权值总和最小的路径,称为最小生成树.求最小生成树的算法有 prim(普里姆)算法 和 kruskal(克鲁斯卡尔)算法: prim算法 : 假设图G=(V,E)是有n个顶点的连通图. T=(U,TE)是G的最小生成树,初值为空.首先从V中任选一个顶点放入U.(标记1:)然后从E中取一条边放入TE,这条边要满足:其中一个顶点在U中,一个在U之外(没在U中)。(这样的边不止一条)。这条边是权值最小的那条.然后把不在U的顶点放入U(这条边的另一端)。jump 标记1. 直到V中所有点都在U中, 这时TE中有n-1条边.最小生成树算法结束.算法时间复杂度是O(n2) 代码示例: package stuct; import java.util.LinkedList; import java.util.List; public class Graph2 { int m = Integer.MAX_VALUE; public static void main(String[] args) { Graph2 main = new Graph2(); main.prim

【树】最小生成树

寵の児 提交于 2020-02-15 03:07:31
kruskal算法 ↑每一次选出合理的最小边,贪心衍生。 #include <iostream> #include<limits.h>//get一个最大宏 using namespace std; const int max1=101; int map[max1][max1],dist[max1],pre[max1]; int prim(int n); { int total=0,min; int i,j,k; bool flag[max1];//flag[i]=true则i选过(已加入最小树集),=false则未选过 for(i=2;i<=n;i++)//从2开始,第一个点特殊定义 { flag[i]=false;//一开始点全部未选过 dist[i]=map[1][i];//把第一层的值先放进dist中 pre[i]=1;//pre记录连接情况,现在所有点都还没有连接 } dist[1]=0; flag[1]=true;//正在处理 for(i=1;i<n;i++)//到n-1结束,最后一个点在处理倒数第二个点时连接 { min=INT_MAX; k=0;//清理现场 for(j=1;j<=n;j++) { if(!flag[j]&&dist[j]<min)//没有被选中的,离当前点最近的点 { min=dist[j]; k=j; } } if(k==0)return -1;/

啊哈!算法阅读笔记(八)——精彩算法

烈酒焚心 提交于 2020-02-15 01:54:35
第八章 更多精彩算法 镖局运镖——图的最小生成树 再谈最小生成树 镖局运镖——图的最小生成树 Kruskal算法: 首先按照边的权值从小到大排序,每次从剩余的边中选择权值较小且边的两个顶点不在同一个集合内的边(不产生回路的边),加入到生成树中,直到加入了n-1条边为止。 再谈最小生成树 Prim算法: 从任意一个顶点开始构造生成树,使用book数组标记已经加入生成树的顶点 用数组dis记录生成树到各个顶点的距离。 从数组dis中选出离生成树最近的顶点(设为j)加入到生成树中。再以j为中间点,更新生成树到每一个非树顶点的距离。 冲入第3步,直到生成树中有n个顶点为止。 来源: CSDN 作者: PURE Li 链接: https://blog.csdn.net/Lip041/article/details/104302080

【数据结构】最小生成树之prim算法和kruskal算法

℡╲_俬逩灬. 提交于 2020-02-15 01:10:51
在日常生活中解决问题经常需要考虑最优的问题,而最小生成树就是其中的一种。看了很多博客,先总结如下,只需要您20分钟的时间,就能完全理解。 比如:有四个村庄要修四条路,让村子能两两联系起来,这时就有最优的问题,怎样修才是做好的,如下图:第一个是网全图,后三个图的修路方案都可以 1.树的定义:有n个顶点和n-1条边,没有回路的称为树 生成树的定义:生成树就是包含全部顶点,n-1(n为顶点数)条边都在图里就是生成树 最小:指的是这些边加起来的权重之和最小 2.判定条件:向生成树中任加一条边都一定构成回路 充分必要条件:最小生成树存在那么图一定是连通的,反过来,图是连通的则最小生成树一定存在 3.和最小生成树有关的两个算法:prim算法和kruskal算法 a)prim算法——让小树慢慢长大型算法 按照树的定义,一个顶点就是一棵树。 原理: 1)我们选择一个顶点,也就是选择了一个树。 2)向外找权重最小的边,这样这棵树就有了两个顶点 3)再以这两个顶点向外找权重最小的边,依次循环,知道所有顶点收到树里 举例: 第一步:选择V1作为顶点 第二步:对比一下与V1相连的各条边的权重,选择最小的V1-V4这条边 第三步:以V1和V4为树,向外找权重最小的边,这时就有了V1-V2,V4-V3两条边,这样就把顶点V2和V3收进了树里。 接着以V1,V2,V3,V4为顶点的树,向外选权值最小的边

最小生成树 Kruscal经典算法

五迷三道 提交于 2020-02-14 03:53:37
    文章作者: ktyanny 文章来源: ktyanny 转载请注明,谢谢合作。   话说ktyanny昨天逃了一天的课,恶补并查集知识,就是为了写出经典得不得了的Kruscal最小生成树。今天早上9点钟爬起来,继续看了下Kruscal算法,顿然茅塞顿开了,哈哈 1、生成树的概念   连通图G的一个子图如果是一棵包含G的所有顶点的树,则该子图称为G的生成树。   生成树是连通图的极小连通子图。所谓极小是指:若在树中任意增加一条边,则将出现一个回路;若去掉一条边,将会使之变成非连通图。 生成树各边的权值总和称为生成树的权。权最小的生成树称为最小生成树。 2、最小生成树的性质   用哲学的观点来说,每个事物都有自己特有的性质,那么图的最小生成树也是不例外的。按照生成树的定义,n 个顶点的连通网络的生成树有 n 个顶点、n-1 条边。 3、构造最小生成树,要解决以下两个问题:   1.尽可能选取权值小的边,但不能构成回路(也就是环)。   2.选取n-1条恰当的边以连接网的 n个顶点。 4、 最小生成树Kruscal算法:   用ktyanny的口头陈述为,Kruscal算法实质是非朴素的贪心策略。初始状态,图的每个节点单独作为一个集合,图的边就绪状态为非降序排列。然后一次遍历图中的所有边(u, v),使用并查集的思想 (不懂并查集的 点击此处 并查集(不相交集合) 进行学习 )

图论算法-最小生成树

和自甴很熟 提交于 2020-02-14 00:28:29
图论算法-最小生成树 在一个无向图中找出一颗 最小生成树(minimum spanning tree) ,这个问题对有向图也是有意义的,不过找起来更困难。最小生成树存在当且仅当图 G G G 是连通的。在最小生成树中边的条数为 ∣ V ∣ − 1 \left | V \right |-1 ∣ V ∣ − 1 。 Prim算法 在每一步,都要把一个节点当作根并往上边加。在算法的任一时刻,我们都可以看到一个已经添加到树上的顶点集,而其余顶点尚未加到这棵树中,此时,算法在每一阶段都可以通过选择边 ( u , v ) (u,v) ( u , v ) ,使得 ( u , v ) (u,v) ( u , v ) 的值是所有 u u u 在树上但 v v v 不在树上的边值中的最小者,而找出一个新的顶点并把它添加到这棵树中。 代码 这里使用的邻接矩阵。 void Prim ( Graph g ) { VertexType adjver [ VERNUM ] ; WeightType lowcost [ VERNUM ] ; int i , j , k ; WeightType min ; // 初始化,一开始生产树中只有开始的顶点 // 这里开始的顶点的编号为 0 for ( i = 0 ; i < g -> vernum ; i ++ ) { lowcost [ i ] = g -> arc

(最小生成树)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【模板】最小生成树