精华内容
下载资源
问答
  • 最小生成树算法

    2020-03-18 22:06:13
    通常, 我们讨论的最小生成树算法都是用于计算加权无向图的最小生成树, 对于有向图, 称之为最小树形图问题. 1.切分定理 切分定理是各类最小生成树算法的基础.首先介绍切分定理. 定义:图的切分是...

    最小生成树:

    定义:图的生成树是它的一棵含有其所有顶点的无环连通子图.一幅加权图的最小生成树是它的一棵权值最小的生成树.
    对于非连通图, 可计算每一连通子图的最小生成树, 合在一起称为最小生成森林.

    通常, 我们讨论的最小生成树算法都是用于计算加权无向图的最小生成树, 对于有向图, 称之为最小树形图问题.

    1.切分定理

    切分定理是各类最小生成树算法的基础.首先介绍切分定理.

    定义:图的切分是将图的所有顶点划分为两个非空且不重叠的子集.某一切分对应的横切边是所有连接两个子集的边.

    切分定理:
    在一幅加权无向图中, 给定任意的切分, 它的横切边中权重最小的横切边必然属于图的最小生成树.(此处假设图中各条边权重均不相同).

    证明:
    使用反证法证明切分定理.假设ee为当前权重最小的横切边, TT为图的最小生成树, 若TT中不包括ee, 则将ee加入到TT中后, 图中包含一条经过ee的环, 且这个环上至少包含与ee属于同一横切的横切边ff,其权重大于ee, 此时删除ff, 可以得到一棵权重更小的生成树,因此当前生成树不是最小生成树. 与假设相矛盾.

    2. 最小生成树的贪心算法

    贪心构造含有V个顶点的连通图的最小生成树
    将属于最小生成树的边标记为黑色, 不属于最小生成树的边标记为灰色. 初始条件下所有边均为灰色. 每次找到一种切分, 其横切边均为灰色, 将权值最小的边添加到生成树中, 直到树中包含V-1条黑色边为止.

    证明:
    由于每次找到的切分其横切边均为灰色, 因此其肯定有一条横切边属于最小生成树.根据切分定理, 权值最小的横切边属于最小生成树, 因此贪心算法中添加的每一条边都属于最小生成树.因此当树中包含V-1条黑色边时, 最小生成树构造完毕.

    3. Prim算法

    Prim最小生成树算法
    基于树中所包含的顶点对图进行切分, 所有切分边均连接树中顶点与非树中顶点. 将权值最小的横切边添加到树中. 当树中有V-1条边时, 最小生成树构造完毕.

    证明:
    由于每次切分的所有横切边均连接树中顶点与非树中顶点,因此其横切边均为灰色, 根据贪心算法的证明, Prim算法可以构造得到最小生成树.

    4. Kruskal算法

    Kruskal算法
    将所有边按照权值大小排序, 依次添加到生成树中, 同时确保加入的边不会构成环, 直至树中包含V-1条边为止.

    证明:Kruskal算法运行过程中会产生多个生成子树, 通过添加新的边, 子树可能被合并, 在算法执行完毕后, 多棵子树将被合并成一棵子树.
    假设当前生成树包括kk个子树, 分别编号为T1,T2,...TkT_1, T_2, ... T_k.其余未在树中的节点每一节点可视为一个独立的子树, 编号为Tk+1,Tk+2...Tk+sT^{'}_{k+1}, T^{'}_{k+2}... T^{'}_{k+s}. 如果当前边ee加入树中后不与树中的边构成环, 则边ee的两个端点不可能同时属于相同的子树编号.假设当前权值最小的边ee两个端点所属子树的编号分别为ii, jj, 则当前边ee可视为属于编号为ii子树与不属于编号为ii子树的两类顶点进行的切分.由于横切边的子树编号不同, 所以横切边不可能是黑色边.所以当前横切边均为灰色边.因此基于贪心切分结论, 当前边ee属于最小生成树.

    展开全文
  • 最小生成树 算法 距离我的资格考试只有十天的路程,我决定离开教科书,改回写作。 毕竟,如果我可以解释这些概念,那么我应该能够通过对它们的测试,对吗? 好吧,今天我很有趣地介绍了算法课程中的一个概念:最小...

    最小生成树 算法

    距离我的资格考试只有十天的路程,我决定离开教科书,改回写作。 毕竟,如果我可以解释这些概念,那么我应该能够通过对它们的测试,对吗? 好吧,今天我很有趣地介绍了算法课程中的一个概念:最小生成树。

    最小生成树概述

    在讨论最小生成树之前,我们需要讨论 特别地,无向图是其边缘没有特定方向的图。 换句话说,它是一个具有沿两个方向连接两个节点的边的图:

    如果要以特殊方式遍历无向图,则可以构造一棵称为生成树的树。 更具体地说, 生成树是图的子集,其中包含所有顶点而没有任何循环。 作为附加标准,生成树必须覆盖最少数量的边:

    但是,如果要将边缘权重添加到无向图,则针对最小边缘数优化树可能不会为我们提供最小生成树。 特别地, 最小生成树是无向加权图的子集,其中包含所有没有任何循环的顶点。 再一次,生成的树必须具有最低的总边缘成本:

    最后一点:最小生成树可能不是唯一的。 换句话说,给定图可能有多个最小生成树。 例如,如果边缘ED的成本为4,我们可以选择ED或BD来完成我们的树。

    顺便说一句,让我们谈谈本文其余部分的情况。 特别是,我们将研究构造最小生成树的两种算法:Prim算法和Kruskal算法。

    最小生成树算法

    如前所述,本文的目的是研究两种主要的最小生成树算法。 两种算法都采用贪婪的方法来解决最小生成树问题,但是它们的处理方式略有不同。

    普里姆算法

    构造最小生成树的一种方法是选择一个起始节点,然后将最便宜的相邻边缘不断添加到树中(避免循环),直到每个节点都已连接为止。 本质上,这就是Prim的算法的工作原理。

    在此示例中,我们从A开始并不断扩展树,直到连接了所有节点。 在这种情况下,我们选择AB,然后选择BC,然后选择CD。 最后,我们得到了成本为12的最小生成树。

    当然,我们本来可以总是从任何其他节点开始以同一棵树结束。 例如,我们可以从D开始,这将在另一个方向上构建树(DC-> CB-> BA)。

    可以想象,这是一个非常简单的贪婪算法,总是构造最小生成树。 当然,需要一些决策来避免产生周期。 就是说,只要新边缘不连接当前树中的两个节点,就不会有任何问题。

    克鲁斯卡尔算法

    构造最小生成树的另一种方法是在所有可用边(避免循环)中连续选择最小的可用边,直到每个节点都已连接。 自然,这就是Kruskal算法的工作原理。

    在此示例中,我们从选择最小边沿开始,在这种情况下为AC。 为了识别这种联系,我们将A和C放在一起。 然后,找到下一个最小边缘AB。 在这种情况下,B尚未包含在包含A的集合中,因此我们可以安全地添加它。

    在这一点上,我们遇到了一个问题。 如果选择BC,则将创建一个循环,因为B和C已通过A连接。由于B和C位于同一集合中,因此我们可以安全地跳过该边。

    最后,我们考虑下一个最小的边缘,即CD。 由于D没有以某种方式连接到C,我们可以将其添加到包含A,B和C的集合中。由于我们的集合现在包含所有四个顶点,因此可以停止。

    不幸的是,这个例子可能不是最好的,因为如果我们从A或C开始,Prim的算法将以类似的方式运行。当然,绘制这些示例会花费一些时间,因此,我建议查看Wikipedia中的PrimKruskal算法。 每个页面都有一个漂亮的动画,显示了差异。

    就我个人而言,我发现该算法在处理方面更具挑战性,因为我发现回避周期标准不太明显。 就是说,正如我在各种教科书中所看到的那样,该解决方案通常依赖于维护代表不同树的集合中节点的集合。 然后,该算法仅选择两个节点(如果它们在不同的树中)。 否则,在节点之间绘制一条边将创建一个循环。

    翻译自: https://www.javacodegeeks.com/2019/09/minimum-spanning-tree-algorithms.html

    最小生成树 算法

    展开全文
  • matlab最小生成树算法

    2018-06-20 23:27:43
    matlab算法,可以解决最小生成树算法以及类似问题关于最小生成树,学过图论的都懂,这里就不做介绍。 下面是一个例题,附有Kruskal算法和Prim算法。
  • 最小生成树 生成树与生成森林 最小生成树 小结与作业 生成树 一定义 图G生成树是G极小连通子图即包含G中所有顶点n与n-1条边连通子图 生成树 V1 V2 V3 V4 V5 V8 V6 V7 V1 V2 V4 V8 V5 V3 V6 V7 V1 V2 V3 V4 V5 V8 V6 ...
  • 最小生成树算法总结

    2020-04-14 15:55:02
    文章目录最小生成树算法框架朴素版primkruskal 最小生成树算法框架 什么是最小生成树? 一个图有 n 个结点,很多条边。最小生成树需要包含原图中的 n 个结点,并且有保持图连通的最少的边,且使这个树的权值达到...

    最小生成树算法框架

    在这里插入图片描述
    什么是最小生成树?
    一个图有 n 个结点,很多条边。最小生成树需要包含原图中的 n 个结点,并且有保持图连通的最少的边,且使这个树的权值达到最小

    遇到稠密图就用朴素版prim,稀疏图就用kruskal即可,堆优化版的prim没有必要掌握。


    朴素版prim

    朴素版 prim 和 dijkstra 算法很像。
    dijkstra 中的 s集合是确定最短路的点
    prim 中的 s集合是已经被加入到最小生成树的点
    在这里插入图片描述
    这里的集合s代表 在当前已经被加入到最小生成树的点。

    每循环一次,都可以将一个点加入 s,循环 n 次后,所有点都可以加入最小生成树了。

    举个例子: 求下图的最小生成树:
    在这里插入图片描述
    ① 我们选 A 为起点,将 A 加入集合s
    在这里插入图片描述
    ② 集合s为{A},与 s 最近的是 D,将 D 加入s
    在这里插入图片描述
    ③ 集合s为{A、D},与 s 最近的是 B,将 B 加入s
    在这里插入图片描述
    ④ 集合s为{A、B、D},与 s 最近的是 E,将 E 加入s
    在这里插入图片描述
    ⑤ 集合s为{A、B、D、E},与 s 最近的是C,将 C 加入s
    在这里插入图片描述
    耶!所有点都进集合了!我们的最小生成树就得到了:)
    在这里插入图片描述
    例题:AcWing 858. Prim算法求最小生成树
    在这里插入图片描述

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std; 
    const int N = 510,INF = 0x3f3f3f3f;
    int n,m;
    int g[N][N]; // 邻接矩阵的存储
    int dist[N]; // 存储点到 集合s 的最短距离 
    bool st[N];  // true为在 集合s 内 
    
    int prim()
    {
    	memset(dist,0x3f,sizeof(dist));
    	
    	int res = 0; //最小生成树的所有边的权重之和 
    	for(int i=0; i<n; i++)
    	{
    		int t = -1;
    		for(int j=1; j<=n; j++) //找到当前在 集合s外 且距离 集合s 最小的点t
    		  if(!st[j] && (t == -1 || dist[t] > dist[j]))
    		    t = j;	
    		
    		if(i && dist[t] == INF) return INF; //当前图不连通,不存在最小生成树
    		if(i) res += dist[t];   //将这个点与集合s中的某相连的点的权值加入答案
    	
    		for(int j=1; j<=n; j++) dist[j] = min(dist[j],g[t][j]);	 //用 t 更新其他点到集合的距离  
    		st[t] = true;  //将 t 加入 集合s 
    	}
    	return res;
    }
    
    int main()
    {
    	cin >> n >> m;
    	memset(g,0x3f,sizeof(g));
    	
    	while(m--)
    	{
    		int a,b,c;
    		scanf("%d%d%d",&a,&b,&c);
    		g[a][b] = g[b][a] = min(g[a][b],c); //无向图相反要建两条变 ,重边的话只取权值最小的 
    	}
    	int  t = prim();
    	
    	if(t == INF) cout<<"impossible";
    	else cout<<t;
    }
    

    注意: 下面这两部顺序不能颠倒的! 要先把那个边的权值加入答案中,再去更新其他点。因为可能出现自环。

    if(i) res += dist[t];   //将这个点与集合s中的某相连的点的权值加入答案
    	
    for(int j=1; j<=n; j++) dist[j] = min(dist[j],g[t][j]);	 //用 t 更新其他点到集合的距离 
    

    举个例子哈 :)
    在这里插入图片描述
    刚开始集合里是A,A将B的dist更新为3,当B进入集合,我们要用B去更新其他点的到集合的最短距离时,B会将自己更新为-2,更新后再将-2加入答案是不对的,因为我们要求的是最小生成树,树是不能有环的,所以要先将3加入答案,再用B更新!!!


    kruskal

    此算法需要用到并查集!排序用 sort 即可。sort的时间复杂度为O(mlogm)
    在这里插入图片描述

    举个例子: 求此图的最小生成树
    在这里插入图片描述
    对所有边排序后,刚开始所有点都是不连通的。
    ① 枚举最小边A——D,A与D不连通,合并A与D
    在这里插入图片描述
    ② 枚举B——E,B与E不连通,合并B与E
    在这里插入图片描述
    ③ 枚举B——C,B与C不连通,合并B与C
    在这里插入图片描述
    ④ 枚举A——C,A与C不连通,合并A与C
    在这里插入图片描述
    ⑤ 枚举D——E,D与E连通,不合并
    ⑥ 枚举A——B,A与B连通,不合并
    ⑦ 枚举C——E,C与E连通,不合并
    ⑧ 所有边都已经枚举过了,最小生成树就得到了:)
    在这里插入图片描述
    例题:AcWing 859. Kruskal算法求最小生成树
    在这里插入图片描述

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std; 
    const int N = 2e5+10;
    int n,m;
    int p[N]; // 并查集的p数组
     
    struct Edge
    {
    	int a,b,w; // a—>b的边权值为w 
    }edges[N]; 
    
    bool cmp(Edge a,Edge b)
    {
       return a.w<b.w;	
    } 
    
    int find(int x) //并查集 
    {
    	if(p[x] != x) p[x] = find(p[x]);
    	return p[x];
    }
    
    void kruskal()
    {
    	sort(edges,edges+m,cmp); //排序
    	
    	for(int i=1; i<=n; i++) p[i] = i; //初始化并查集
    	
    	int res = 0, cnt = 0;
    	for(int i=0; i<m; i++)  //从小到大枚举所有边 
    	{
    		int a = edges[i].a, b = edges[i].b, w = edges[i].w;
    		if(find(a) != find(b)) //判断 a 和 b 是否连通
    		{
    		   p[find(a)] = b; //合并 
    		   res += w;	//最小生成树的所有树边权值之和
    		   cnt++;   //当前最小生成树的边数
    		} 
    	}
    	if(cnt < n-1) cout<<"impossible"; //小于 n-1 说明不连通
    	else cout<<res; 
    }
    int main()
    {
    	cin >> n >> m;
    	for(int i=0; i<m; i++)
    	{
    		int a, b, w;
    		scanf("%d%d%d",&a,&b,&w);
    		edges[i] = {a,b,w};
    	}
        kruskal();
        return 0;
    }
    
    展开全文
  • 输入:城市个数N 输出:建设通信网络的结构和最低成本(距离即成本) 说明:主函数调用prepare函数准备城市坐标及各城市间距离等数据,并调用最小生成树算法primMST primMST算法根据城市网络图获得最小生成树
  • 最小生成树算法–kruscal算法

    最小生成树算法–kruscal算法

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 最小生成树算法理解

    2018-07-31 15:53:39
    最小生成树算法理解 最小生成树的算法主要有两种Kruskal算法和Prim算法;Kruskal算法是通过逐个找短的边来去找点,最后实现最小生成树;而Prim算法是由先确定一点去找边,再通过点去找短边来实现最小生成树的。 ...
  • Prim最小生成树算法

    2015-05-25 15:59:16
    刷题遇到一道Prim最小生成树算法的实现的题目,重新温习一下最小生成树算法

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,863
精华内容 6,745
关键字:

最小生成树算法