当前位置: 首页 > article >正文

数据结构与算法学习笔记----Prim算法

数据结构与算法学习笔记----Prim算法

@@ author: 明月清了个风
@@ first publish time: 2024.12.21

Prim算法

Prim算法是一种基于贪心策略的最小生成树求解算法,和Dijkstra很相似。

最小生成树

最小生成树(Minimum Spanning Tree, MST)是图论中的经典问题,对于一个无向带权图,它指的是一个包含图中所有顶点的生成树,其中边的权值和最小,它的性质主要有下面三个

  1. 最小生成树包含所有的顶点
  2. 最小生成树中没有环
  3. 边的权值和最小。

基本思想

  1. 从图中任意一个顶点出发,逐步扩展生成树
  2. 在已经生成的树的基础上,选择在树外距离与树连通并距离最近的节点加入树中,并用该点的出边更新其他点到树的距离
  3. 重复该过程,直到生成树包含了所有的节点。

通过与Dijkstra算法对比可以发现,两个算法步骤的唯一区别在于上述思想中的第二步,对于Dijkstra来说,我们选择的是在已经确定最短距离的点集外的点中距离源点距离最近的点,而Prim算法选择是已经包含在树中之外的点中距离树中任意节点距离最近的点。

两者的区别在于更新其他点的距离的时候,对于Dijkstra来说,更新距离是

for(int j = 1; j  <= n; j ++)
    dist[j] = min(dist[j], dist[t] + g[t][j]);

对于Prim算法来说

for(int j = 1; j  <= n; j ++)
    dist[j] = min(dist[j], g[t][j]);

时间复杂度

Floyd算法的时间复杂度为 O ( n 3 ) O(n^3) O(n3) n n n表示节点数。

Acwing 858. Prim算法求最小生成树

[原题链接](858. Prim算法求最小生成树 - AcWing题库)

给定一个 n n n个点 m m m条边的有向图,图中可能存在重边和自环,边权可能为负数。

求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible

给定一张边带权的无向图 G = ( V , E ) G=(V,E) G=(V,E),其中 V V V表示图中点的集合, E E E表示图中边的集合, n = ∣ V ∣ n=|V| n=V m = ∣ E ∣ m=|E| m=E

V V V中的全部 n n n个顶点和 E E E n − 1 n-1 n1条边构成的无向连通子图被称为 G G G的一棵生成树,其中边的权值之和最小的生成树被称为无向图 G G G的最小生成树。

输入格式

第一行包含三个整数 n n n, m m m

接下来 m m m行,每行包含三个整数 x x x y y y z z z,表示存在一条从点 x x x到点 y y y的有向边,边长为 z z z

输出格式

共一行,若存在最小生成树,则输出一个整数,表示最小生成树的树边权重之和,如果最小生成树不存在则输出impossible.

数据范围

1 ≤ n ≤ 500 1 \leq n \leq 500 1n500,

1 ≤ m ≤ 1 0 5 1 \leq m \leq 10^5 1m105,

图中涉及边长绝对值均不超过 10000 10000 10000.

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 510, inf = 0x3f3f3f3f;

int n, m;
int dist[N];
int g[N][N];
bool st[N];

int prim()
{
    int res = 0;
    
    memset(dist, 0x3f, sizeof dist);
    
    for(int i = 0; i < n; i ++)
    {
        int t = -1;
        for(int j = 1; j <= n; j ++)
        {
            if(!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        }
        st[t] = true;
        if(i && dist[t] == inf) return inf;
        if(i) res += dist[t];   // 这里有个注意点是要先更新答案res再去更新边权,因为可能有负权自环,这个dist[t]可能会把自己变小。
        
        for(int j = 1; j <= n; j ++)
            dist[j] = min(dist[j], g[t][j]);
    }
    
    return res;
}

int main()
{
    cin >> n >> m;
    
    memset(g, 0x3f, sizeof g);
    
    for(int i = 0; i < m; i ++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(g[a][b], c);
    }
    
    int t = prim();
    if(t == inf) puts("impossible");
    else cout << t << endl;
    
    return 0;
}

http://www.kler.cn/a/446738.html

相关文章:

  • 游戏AI实现-寻路算法(A*)
  • GhostRace: Exploiting and Mitigating Speculative Race Conditions-记录
  • Azure虚拟机非托管磁盘大小调整
  • fastdds:idl
  • 免费GIS工具箱:轻松将glb文件转换成3DTiles文件
  • WordPress 去除?v= 动态后缀
  • 复盘:“辩论赛”复盘
  • 容联云孔淼:金融数智化深水区,从数字化工具到业务变革提效
  • 驾考科目一考什么?
  • 感受野如何计算?
  • vtie项目中使用到了TailwindCSS,如何打包成一个单独的CSS文件(优化、压缩)
  • 阿里云OSS批量导出下载地址 OSS批量导出 OSS导出清单
  • 应用端sql慢查询监控分析
  • git全教程(长期更新)
  • Leetcode分隔链表
  • 急!急!急!电脑丢失msvcr100.dll怎么办?电脑“缺失msvcr100.dll”要怎么解决?
  • 使用计算机创建一个虚拟世界
  • 【P2P】【Go】采用go语言实现udp hole punching 打洞 传输速度测试 ping测试
  • 《XML》教案 第1章 学习XML基础
  • C# OpenCV机器视觉:图像拼接
  • 重拾设计模式--建造者模式
  • MFC/C++学习系列之简单记录8——消息映射
  • 2.6 网络面试问题
  • 二叉树 -- 堆(详解)
  • 网安信息收集(web层面)
  • springboot——登录认证(包括jwt技术、拦截器过滤器)