图论13-最小生成树-Kruskal算法+Prim算法

这篇具有很好参考价值的文章主要介绍了图论13-最小生成树-Kruskal算法+Prim算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 最小生成树

图论13-最小生成树-Kruskal算法+Prim算法,图论,图论,算法

2 最小生成树Kruskal算法的实现

2.1 算法思想

  1. 基本思想:按照权值从小到大的顺序选择 n-1 条边,并保证这 n-1 条边不构成回路
  2. 具体做法:首先构造一个只含 n 个顶点的森林,然后依权值从小到大从连通网中选择边加入到森林中,并使森林中不产生回路,直至森林变成一棵树为止。

图论13-最小生成树-Kruskal算法+Prim算法,图论,图论,算法

2.2 算法实现

2.2.1 如果图不联通,直接返回空,该图没有mst

 CC cc = new CC(G);
 
 if(cc.count() > 1) return;

2.2.2 获得图中的所有边,并且进行排序

ArrayList<WeightedEdge> edges = new ArrayList<>();

for(int v = 0; v < G.V(); v ++)
    for(int w: G.adj(v))
        if(v < w) // 剪枝:0-2,2-0,只判断0-2,避免重复
            edges.add(new WeightedEdge(v, w, G.getWeight(v, w)));

Collections.sort(edges);
2.2.2.1 Edge类要实现Comparable接口,并重写compareTo方法
public int compareTo(WeightedEdge another){
    return weight - another.weight;
}

2.2.3 取边进行判断是否形成环

2.2.3.1判断是否形成环

通过并查集标记联通分量。

如果添加进来的边的两个顶点属于不同的集合,那么说明不会形成环。

如果添加进来的边的两个顶点属于相同的集合,那么说明一定形成环。

UF uf = new UF(G.V());
for(WeightedEdge edge: edges){
    int v = edge.getV();
    int w = edge.getW();

    // 判断选择的边的两个顶点是否属相连
    if(!uf.isConnected(v, w)){ 
        mst.add(edge);
        uf.unionElements(v, w); // 合并两个顶点和边
    }
}

图论13-最小生成树-Kruskal算法+Prim算法,图论,图论,算法

3 最小生成树Prim算法的实现

3.1 算法思想

Prim的核心思想就是使用贪心算法,每次从连通图中找到一条符合条件的权值最小的边,重复这样的操作N-1次,选出的N-1条权值最小的边组成的树就是最下生成树。

将顶点分为两类,一类是在查找的过程中已经包含在树中的(假设为 B 类),剩下的是另一类(假设为 A 类)。

3.2 算法实现

3.2.1 如果图不联通,直接返回空,该图没有mst

 CC cc = new CC(G);
 
 if(cc.count() > 1) return;

3.2.2 使用visited数组区分A组B组

初始化的时候visited数组起始的元素为true,其余全部设置为galse,表示两个不同的组

boolean visited[] = new boolean[G.V()];
visited[0] = true;

3.2.3 添加边生成mst

声明一个变量minEdge用于标记权重最小的边。

for(int i = 1; i < G.V(); i ++){
    WeightedEdge minEdge = new WeightedEdge(-1, -1, Integer.MAX_VALUE);
    for(int v = 0; v < G.V(); v ++)
        if(visited[v]) //当前组的节点进行遍历
            for(int w: G.adj(v)) //找到相邻的顶点
            // 如果当前的顶点跟上一个顶点不是一个组
            // 并且权重比minEdge标记的权重更小
                if(!visited[w] && G.getWeight(v, w) < minEdge.getWeight())
                // 更新minEdge的值,并加入到mst中
                    minEdge = new WeightedEdge(v, w, G.getWeight(v, w));
    mst.add(minEdge);
    visited[minEdge.getV()] = true;
    visited[minEdge.getW()] = true;
}

3.2.4 切分优化 - (一定要掌握)

使用优先队列取最短的边。

拓展的过程中,优先队列的边不一定是合法的边。

在构建mst时进行判断边的合法性。文章来源地址https://www.toymoban.com/news/detail-788788.html

 Queue pq = new PriorityQueue<WeightedEdge>();
 // 初始化
 for(int w: G.adj(0))
     pq.add(new WeightedEdge(0, w, G.getWeight(0, w)));

// 循环取边
 while(!pq.isEmpty()){

     WeightedEdge minEdge = (WeightedEdge) pq.remove();

		// 判断边的合法性
     if(visited[minEdge.getV()] && visited[minEdge.getW()])
         continue; //  继续循环取边

     mst.add(minEdge);

     int newv = visited[minEdge.getV()] ? minEdge.getW() : minEdge.getV(); // 找到新边不属于同一集合的点
     visited[newv] = true; //设置为同一集合
	
	 // 更新横切边的优先队列
     for(int w: G.adj(newv))
         if(!visited[w])
             pq.add(new WeightedEdge(newv, w, G.getWeight(newv, w)));
 }

到了这里,关于图论13-最小生成树-Kruskal算法+Prim算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 最小生成树(Prim算法,Kruskal算法)

    (1)生成树: 如果在一个无向连通图不包含回路(连通图中不存在环),则为一个树 (2)最小生成树(minimal spanning tree): 在一个图所有生成树中,代价最小的生成树称为最小生成树 (3)生成树的代价: 在一个无向连通网中,生成树各边的权值之和称为该生成树的代价

    2024年02月08日
    浏览(35)
  • 最小生成树—Kruskal算法和Prim算法

    连通图:在无向图中,若从顶点v1到顶点v2有路径,则称顶点v1与顶点v2是连通的。如果图中任 意一对顶点都是连通的,则称此图为连通图。 生成树:一个连通图的最小连通子图称作该图的生成树。有n个顶点的连通图的生成树有n个顶点 和n-1条边。 最小生成树:构成生成树的

    2024年02月05日
    浏览(36)
  • 最小生成树(Prim算法与Kruskal算法)

    一个连通图的生成树是一个极小的连通子图,它含有图中全部的n个顶点,但只有足以构成一棵树的n-1条边。我们把构造连通网的最小代价生成树称为最小生成树。 例如下图中①、②、③都是左侧图的生成树,但③是构造连通网的最小代价,所以③是该图的最小生成树。 P

    2024年02月05日
    浏览(50)
  • 最小(代价)生成树—Prim算法与Kruskal算法

    目录  一、最小生成树的特点 二、最小生成树算法  ① Prim(普里姆)算法 ②Kruskal(克鲁斯卡尔)算法  ③Prim算法与Kruskal算法对比 最小生成树是带权连通图G=(V,E)的生成树中边的权值之和最小的那棵生成树。它具有以下特点: 图G中各边权值互不相等时有唯一的最小生成树。图

    2024年02月01日
    浏览(30)
  • 最小生成树Kruskal、Prim算法C++

    连通图: 在无向图中,若从顶点v1到顶点v2有路径,则称顶点v1和顶点v2是连通的。如果图中任意一对顶点都是连通的,则称此图为连通图。 生成树: 一个连通图的最小连通子图称作为图的生成树。有 n个顶点 的连通图的生成树有 n个顶点和 n-1 条边。 最小生成树: 最小生活

    2024年02月10日
    浏览(33)
  • 【最小生成树】一文学懂prim、kruskal算法

    博主简介: 努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享:算法、数据结构、Java等相关知识。 博主主页: @是瑶瑶子啦 所属专栏: 算法 ;该专栏专注于蓝桥杯和ACM等算法竞赛🔥 近期目标: 写好专栏的每一篇文章 首先,我们要了解什么是最小生

    2023年04月25日
    浏览(25)
  • 用prim和kruskal算法求最小生成树问题

    题目 http://ybt.ssoier.cn:8088/problem_show.php?pid=1350 信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn) http://ybt.ssoier.cn:8088/problem_show.php?pid=1391 相当于一个图中求最小生成树的问题 prim解决 kruskal解法 信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn) http://ybt.ssoier.cn:8088/problem_show.ph

    2024年02月09日
    浏览(29)
  • C语言实现最小生成树算法:Prim和Kruskal

    以下是使用C语言实现Prim算法生成最小生成树的代码: 注释如下: #include stdio.h 和 `#include #define V 5 定义了图中顶点的个数为5。 int minDistance(int dist[], int visited[]) 函数用于找到顶点集合中未访问的顶点中距离最小的顶点。输入参数 dist 用于存储顶点到最小生成树的距离,输入

    2024年02月03日
    浏览(35)
  • 求最小生成树Prim(普里姆)和Kruskal(克鲁斯卡尔)算法

     想求最小生成树,我们首先得弄懂以下几个概念   连通图 :图中任意两个顶点都是连通的 极小连通子图 :既要保持图连通又要使得边数最少的子图 生成树 : 包含图中全部顶点的一个极小连通子图 连通图用通俗的话来讲就是,某一个顶点,可以 直接或者间接 (通过其他顶点

    2024年02月05日
    浏览(38)
  • 【数据结构与算法】最小生成树之普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法

      🌱博客主页:大寄一场. 🌱系列专栏:数据结构与算法 😘博客制作不易欢迎各位👍点赞+⭐收藏+➕关注 目录 前言 一、最小生成树的概念 二、最小生成树的求解方法 三、练习题 四、最小生成树在实际应用中的例子 最近非科班的同学学到了最小生成树并询问我,于是想趁

    2024年02月07日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包