【Awcing练习题-858.Prim算法求最小生成树】

分类-第三章 搜索与图论-最小生成树

题目

给定一个 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

由 𝑉 中的全部 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 行,每行包含三个整数 u , v , w u,v,w u,v,w,表示点 u u u 和点 v v v 之间存在一条权值为 w w w 的边。

输出格式

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

数据范围

1 ≤ n ≤ 500 , 1≤n ≤500, 1n500,
1 ≤ m ≤ 1 0 5 , 1≤m≤10^5, 1m105,
图中涉及边的边权的绝对值均不超过 10000。

输入样例

4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4

输出样例

6

解题前的"废话"

什么是最小生成树?

一个有 n n n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n n n个结点,并且有保持图连通的最少的边。 [1]最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。(来自百度百科)

极小连通子图中边权和最小的就是最小生成树,当然如果边权和出现相同的情况,就说明最小生成树不唯一,所以一般结果是求值。

什么是Prim算法?—适合边多点少

从个人理解来说, P r i m Prim Prim就是一个不断找最小边的算法(先找边,再确定点)。首先分为两个点集, s t st st代表被选中的点集,另外一个点集代表未被选中。开始前st为空,选择从任意一点出发,并加入 s t st st。选择与所选点集相连最小的边,每次确定边之前,保证之前所选边不会成环。重复选边、判断的步骤,直到所有点被选中。

思路(结合代码一起看)

大体思路是,我们要将我们的手算模拟思路转化为代码,再加上代码优化,更简洁美观(为了偷懒)。

先定义三个数组:

s t [ N ] 、 d i s t [ N ] 、 g [ N ] [ N ] , st[N]、dist[N]、g[N][N], st[N]dist[N]g[N][N]

分别代表已选点集、点集中任意一点到点 Vi 的距离,以及任意两点之间的距离。

(1)一共有 n n n个点,我们需要循环遍历$ n $次,直到每个点都被选中。

(2)开始时任意选一个点。假设第一次选V1 ,加入st集合(其实第一次进入双重for循环其实什么都没干)。更新每个点到V1的最短距离,然后进入下一次循环。

(3)(正式开始)每次选未被选择过的点Vj,即st[j]=false,且Vj到集合st中的某一个点是所有边种最短的(第二重for循环中有体现);如果没有最短的边(都是INF),那么就说明不存在最小生成树,返回无穷大INF。
(4)有两个点了 (i不为0了),最小生成树中就存在一条边了,加入存储答案的res。
(5)然后重复步骤(2),将选中的点 Vt 加入点集 s t st st

示例

选择从任意一点出发,此处选择V1

在这里插入图片描述
更新所有到已选的点集合(黄色所圈的点)的最短距离,找出最短的边(V1V0
在这里插入图片描述将点V0加入点集

在这里插入图片描述
更新边,选择最短的边(V0V5
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
选择最短(V1V8) (dist[6]=6,记录的是最短的边)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
中间步骤一样跳过,来看下一下特殊的情况(dist[3]=11): 最短边是(V5V6),但V5V6已经是st 集合中的点了,所以不能加入(V1V2)这条边也是,所以剔除这两条边,最终第二重循环选出来的t=7,也就是V7
在这里插入图片描述
直到所有点被选中,得到的结果就是最小生成树。当然在选的过程中,最短边如果有两条,且符合选择条件,则最小生成树是不唯一的。
在这里插入图片描述

代码

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

using namespace std;

const int N=510,M=1e5, INF=0x3f3f3f3f;
int n,m;
int g[N][N];//邻接矩阵存储权
bool st[N];//存储在集合中的点
int dist[N];//存储某点到集合的距离

int prim()
{
    //
    memset(dist,0x3f,sizeof dist);
    int res=0;//用来存储最小生成树边的和

    for(int i=0;i<n;i++) //循环n次,每次找到一个点加入集合
    {
        int t=-1;
        //这里是寻找离集合最短的边
        for(int j=1;j<=n;j++)//从节点1~n
            if(!st[j]&&(t==-1||dist[j]<dist[t]))
                t=j;//更新成较短的
        //找到最短的边之后,先更新最小树边之和,而不是更新边
        //如果有自环,且自环路最短,则自环边会被更新为短边然后算入最小生成树
        //先加入点的集合,则不会考虑自环边
        if(i&&dist[t]==INF) return INF;//如果找不到更新点了则说明无

        if(i) res+=dist[t];
        st[t]=true;//t被放入最小树点集合

        //更新集合中刚加入的点与节点j连接的边
        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);
    while(m--)
    {
        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;
}

(算法小白,写博客为了对算法理解更透彻。如有错误,望大佬指点,欢迎交流!)

相关推荐

  1. prim算法生成

    2024-04-23 00:50:01       32 阅读
  2. 生成 prim + kruskal

    2024-04-23 00:50:01       28 阅读
  3. 生成——Prim/Kruskal Python

    2024-04-23 00:50:01       25 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-23 00:50:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-23 00:50:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-23 00:50:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-23 00:50:01       18 阅读

热门阅读

  1. STM32 CAN发送邮箱和接收FIFO

    2024-04-23 00:50:01       9 阅读
  2. 若依学习记录

    2024-04-23 00:50:01       12 阅读
  3. 聚类算法的学习

    2024-04-23 00:50:01       11 阅读
  4. uniapp微信小程序蓝牙连接与设备数据对接

    2024-04-23 00:50:01       12 阅读
  5. 《1w实盘and大盘基金预测 day25》

    2024-04-23 00:50:01       11 阅读
  6. 笨蛋学C++【C++基础第三弹】

    2024-04-23 00:50:01       11 阅读
  7. element UI 走马灯 initial-index动态赋值 不生效问题

    2024-04-23 00:50:01       12 阅读
  8. 【华为OD机试】最长连续手牌【C卷|200分】

    2024-04-23 00:50:01       9 阅读
  9. 金融风险评估都有什么模型

    2024-04-23 00:50:01       13 阅读
  10. iOS(Object C) 冒泡排序

    2024-04-23 00:50:01       14 阅读
  11. Android R 展讯平台关机充电动画横屏显示修改

    2024-04-23 00:50:01       13 阅读
  12. PyTorch: 点燃深度学习革新之火

    2024-04-23 00:50:01       16 阅读