0053.寻宝-prim

1. 删掉文章中冗余的空格,但不包括1代码中的空格和2结构性空格(如标题内)等合理空格
2. 将总结部分倒数第三句中"如何求职最小生成树的每一条边"的"求职"修改为"获得"
This commit is contained in:
swjtuhjf
2024-11-07 23:44:18 +08:00
parent 90fece312b
commit 9e6cc0e627

View File

@ -9,17 +9,17 @@
在世界的某个区域,有一些分散的神秘岛屿,每个岛屿上都有一种珍稀的资源或者宝藏。国王打算在这些岛屿上建公路,方便运输。
不同岛屿之间,路途距离不同,国王希望你可以规划建公路的方案,如何可以以最短的总公路距离将 所有岛屿联通起来。
不同岛屿之间,路途距离不同,国王希望你可以规划建公路的方案,如何可以以最短的总公路距离将所有岛屿联通起来。
给定一张地图,其中包括了所有的岛屿,以及它们之间的距离。以最小化公路建设长度,确保可以链接到所有岛屿。
输入描述:
第一行包含两个整数VEV代表顶点数E代表边数 。顶点编号是从1到V。例如V=2一个有两个顶点分别是1和2。
第一行包含两个整数VEV代表顶点数E代表边数。顶点编号是从1到V。例如V=2一个有两个顶点分别是1和2。
接下来共有 E 行,每行三个整数 v1v2valv1v2 为边的起点和终点val代表边的权值。
接下来共有E每行三个整数v1v2valv1v2为边的起点和终点val代表边的权值。
输出描述:
输出描述:
输出联通所有岛屿的最小路径总距离
@ -38,65 +38,65 @@
5 6 2
5 7 1
6 7 1
```
```
输出示例:
输出示例:
6
## 解题思路
## 解题思路
本题是最小生成树的模板题,那么我们来讲一讲最小生成树。
本题是最小生成树的模板题,那么我们来讲一讲最小生成树。
最小生成树 可以使用 prim算法 也可以使用 kruskal算法计算出来。
最小生成树可以使用prim算法也可以使用kruskal算法计算出来。
本篇我们先讲解 prim算法。
本篇我们先讲解prim算法。
最小生成树是所有节点的最小连通子图, 即:以最小的成本(边的权值)将图中所有节点链接到一起。
最小生成树是所有节点的最小连通子图,即:以最小的成本(边的权值)将图中所有节点链接到一起。
图中有n个节点那么一定可以用 n - 1 条边将所有节点连接到一起。
图中有n个节点那么一定可以用n-1条边将所有节点连接到一起。
那么如何选择n-1 条边 就是 最小生成树算法的任务所在。
那么如何选择n-1条边就是最小生成树算法的任务所在。
例如本题示例中的无向有权图为:
例如本题示例中的无向有权图为:
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231206164306.png)
那么在这个图中,如何选取 n-1 条边 使得 图中所有节点连接到一起,并且边的权值和最小呢?
那么在这个图中如何选取n-1条边使得图中所有节点连接到一起并且边的权值和最小呢
图中为n为7即7个节点那么只需要 n-16条边就可以讲所有顶点连接到一起
图中为n为7即7个节点那么只需要n-16条边就可以讲所有顶点连接到一起
prim算法 是从节点的角度 采用贪心的策略 每次寻找距离 最小生成树最近的节点 并加入到最小生成树中。
prim算法是从节点的角度采用贪心的策略每次寻找距离最小生成树最近的节点并加入到最小生成树中。
prim算法核心就是三步我称为**prim三部曲**,大家一定要熟悉这三步,代码相对会好些很多:
prim算法核心就是三步我称为**prim三部曲**,大家一定要熟悉这三步,代码相对会好些很多:
1. 第一步,选距离生成树最近节点
2. 第二步,最近节点加入生成树
2. 第二步,最近节点加入生成树
3. 第三步更新非生成树节点到生成树的距离即更新minDist数组
现在录友们会对这三步很陌生,不知道这是干啥的,没关系,下面将会画图举例来带大家把这**prim三部曲**理解到位。
现在录友们会对这三步很陌生,不知道这是干啥的,没关系,下面将会画图举例来带大家把这**prim三部曲**理解到位。
在prim算法中有一个数组特别重要这里我起名为minDist。
刚刚我有讲过 “每次寻找距离 最小生成树最近的节点 并加入到最小生成树中”,那么如何寻找距离最小生成树最近的节点呢?
刚刚我有讲过“每次寻找距离最小生成树最近的节点并加入到最小生成树中”,那么如何寻找距离最小生成树最近的节点呢?
这就用到了 minDist 数组, 它用来作什么呢?
这就用到了minDist数组它用来作什么呢
**minDist数组 用来记录 每一个节点距离最小生成树的最近距离**。 理解这一点非常重要,这也是 prim算法最核心要点所在很多录友看不懂prim算法的代码都是因为没有理解透 这个数组的含义。
**minDist数组用来记录每一个节点距离最小生成树的最近距离**。理解这一点非常重要这也是prim算法最核心要点所在很多录友看不懂prim算法的代码都是因为没有理解透这个数组的含义。
接下来,我们来通过一步一步画图,来带大家巩固 **prim三部曲** 以及 minDist数组 的作用。
接下来,我们来通过一步一步画图,来带大家巩固**prim三部曲**以及minDist数组的作用。
**示例中节点编号是从1开始所以为了让大家看的不晕minDist数组下标我也从 1 开始计数下标0 就不使用了,这样 下标和节点标号就可以对应上了,避免大家搞混**
**示例中节点编号是从1开始所以为了让大家看的不晕minDist数组下标我也从1开始计数下标0就不使用了这样下标和节点标号就可以对应上了避免大家搞混**
### 1 初始状态
### 1 初始状态
minDist 数组 里的数值初始化为 最大数,因为本题 节点距离不会超过 10000所以 初始化最大数为 10001就可以。
minDist数组里的数值初始化为最大数因为本题节点距离不会超过10000所以初始化最大数为10001就可以。
相信这里录友就要问了,为什么这么做?
相信这里录友就要问了,为什么这么做?
现在 还没有最小生成树,默认每个节点距离最小生成树是最大的,这样后面我们在比较的时候,发现更近的距离,才能更新到 minDist 数组上。
现在还没有最小生成树默认每个节点距离最小生成树是最大的这样后面我们在比较的时候发现更近的距离才能更新到minDist数组上。
如图:
@ -108,125 +108,125 @@ minDist 数组 里的数值初始化为 最大数,因为本题 节点距离不
1、prim三部曲第一步选距离生成树最近节点
选择距离最小生成树最近的节点加入到最小生成树刚开始还没有最小生成树所以随便选一个节点加入就好因为每一个节点一定会在最小生成树里所以随便选一个就好那我们选择节点1 符合遍历数组的习惯第一个遍历的也是节点1
选择距离最小生成树最近的节点加入到最小生成树刚开始还没有最小生成树所以随便选一个节点加入就好因为每一个节点一定会在最小生成树里所以随便选一个就好那我们选择节点1符合遍历数组的习惯第一个遍历的也是节点1
2、prim三部曲第二步最近节点加入生成树
2、prim三部曲第二步最近节点加入生成树
此时 节点1 已经算最小生成树的节点。
此时节点1已经算最小生成树的节点。
3、prim三部曲第三步更新非生成树节点到生成树的距离即更新minDist数组
接下来,我们要更新所有节点距离最小生成树的距离,如图:
接下来,我们要更新所有节点距离最小生成树的距离,如图:
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102048.png)
注意下标0我们就不管它了下标 1 与节点 1 对应,这样可以避免大家把节点搞混。
注意下标0我们就不管它了下标1与节点1对应,这样可以避免大家把节点搞混。
此时所有非生成树的节点距离 最小生成树节点1的距离都已经跟新了
此时所有非生成树的节点距离最小生成树节点1的距离都已经跟新了
* 节点2节点1 的距离为1比原先的 距离值10001小所以更新minDist[2]。
* 节点3节点1 的距离为1比原先的 距离值10001小所以更新minDist[3]。
* 节点5节点1 的距离为2比原先的 距离值10001小所以更新minDist[5]。
* 节点2节点1的距离为1比原先的距离值10001小所以更新minDist[2]。
* 节点3节点1的距离为1比原先的距离值10001小所以更新minDist[3]。
* 节点5节点1的距离为2比原先的距离值10001小所以更新minDist[5]。
**注意图中我标记了 minDist数组里更新的权值**,是哪两个节点之间的权值,例如 minDist[2] =1 ,这个 1 是 节点1 与 节点2 之间的连线,清楚这一点对最后我们记录 最小生成树的权值总和很重要。
**注意图中我标记了minDist数组里更新的权值**是哪两个节点之间的权值例如minDist[2]=1这个1是节点1与节点2之间的连线清楚这一点对最后我们记录最小生成树的权值总和很重要。
(我在后面依然会不断重复 prim三部曲可能基础好的录友会感觉有点啰嗦但也是让大家感觉这三部曲求解的过程
我在后面依然会不断重复prim三部曲可能基础好的录友会感觉有点啰嗦但也是让大家感觉这三部曲求解的过程
### 3
### 3
1、prim三部曲第一步选距离生成树最近节点
选取一个距离 最小生成树节点1 最近的非生成树里的节点节点235 距离 最小生成树节点1 最近,选节点 2其实选 节点3或者节点2都可以距离一样的加入最小生成树。
选取一个距离最小生成树节点1最近的非生成树里的节点节点235距离最小生成树节点1最近选节点2其实选节点3或者节点2都可以距离一样的加入最小生成树。
2、prim三部曲第二步最近节点加入生成树
2、prim三部曲第二步最近节点加入生成树
此时 节点1节点2已经算最小生成树的节点。
此时节点1节点2已经算最小生成树的节点。
3、prim三部曲第三步更新非生成树节点到生成树的距离即更新minDist数组
接下来,我们要更新节点距离最小生成树的距离,如图:
接下来,我们要更新节点距离最小生成树的距离,如图:
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102431.png)
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102431.png)
此时所有非生成树的节点距离 最小生成树节点1、节点2的距离都已经跟新了
此时所有非生成树的节点距离最小生成树节点1、节点2的距离都已经跟新了
* 节点3节点2 的距离为2和原先的距离值1 小,所以不用更新。
* 节点4节点2 的距离为2比原先的距离值10001小所以更新minDist[4]。
* 节点5节点2 的距离为10001不连接所以不用更新。
* 节点6节点2 的距离为1比原先的距离值10001小所以更新minDist[6]。
* 节点3节点2的距离为2和原先的距离值1小所以不用更新。
* 节点4节点2的距离为2比原先的距离值10001小所以更新minDist[4]。
* 节点5节点2的距离为10001不连接所以不用更新。
* 节点6节点2的距离为1比原先的距离值10001小所以更新minDist[6]。
### 4
### 4
1、prim三部曲第一步选距离生成树最近节点
选择一个距离 最小生成树节点1、节点2 最近的非生成树里的节点节点36 距离 最小生成树节点1、节点2 最近选节点3 选节点6也可以距离一样加入最小生成树。
选择一个距离最小生成树节点1、节点2最近的非生成树里的节点节点36距离最小生成树节点1、节点2最近选节点3选节点6也可以距离一样加入最小生成树。
2、prim三部曲第二步最近节点加入生成树
2、prim三部曲第二步最近节点加入生成树
此时 节点1 、节点2 、节点3 算是最小生成树的节点。
此时节点1、节点2、节点3算是最小生成树的节点。
3、prim三部曲第三步更新非生成树节点到生成树的距离即更新minDist数组
接下来更新节点距离最小生成树的距离,如图:
接下来更新节点距离最小生成树的距离,如图:
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102457.png)
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102457.png)
所有非生成树的节点距离 最小生成树节点1、节点2、节点3 )的距离都已经跟新了
所有非生成树的节点距离最小生成树节点1、节点2、节点3的距离都已经跟新了
* 节点 4 和 节点 3的距离为 1和原先的距离值 2 所以更新minDist[4]为1。
* 节点4和节点3的距离为1和原先的距离值2所以更新minDist[4]为1。
上面为什么我们只比较 节点4节点3 的距离呢?
上面为什么我们只比较节点4节点3的距离呢
因为节点3加入 最小生成树后,非 生成树节点 只有 节点 4 和 节点3是链接的所以需要重新更新一下 节点4距离最小生成树的距离其他节点距离最小生成树的距离 都不变。
因为节点3加入最小生成树后非生成树节点只有节点4和节点3是链接的所以需要重新更新一下节点4距离最小生成树的距离其他节点距离最小生成树的距离都不变。
### 5
### 5
1、prim三部曲第一步选距离生成树最近节点
继续选择一个距离 最小生成树节点1、节点2、节点3 最近的非生成树里的节点,为了巩固大家对 minDist数组的理解这里我再啰嗦一遍
继续选择一个距离最小生成树节点1、节点2、节点3最近的非生成树里的节点为了巩固大家对minDist数组的理解这里我再啰嗦一遍
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231217213516.png)
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231217213516.png)
**minDist数组 是记录了 所有非生成树节点距离生成树的最小距离**,所以 从数组里我们能看出来,非生成树节点 4 和 节点 6 距离 生成树最近。
**minDist数组是记录了所有非生成树节点距离生成树的最小距离**,所以从数组里我们能看出来,非生成树节点4和节点6距离生成树最近。
任选一个加入生成树,我们选 节点4选节点6也行
任选一个加入生成树我们选节点4选节点6也行
**注意**,我们根据 minDist数组选取距离 生成树 最近的节点 加入生成树,那么 **minDist数组里记录的其实也是 最小生成树的边的权值**(我在图中把权值对应的是哪两个节点也标记出来了)。
**注意**我们根据minDist数组选取距离生成树最近的节点加入生成树那么**minDist数组里记录的其实也是最小生成树的边的权值**(我在图中把权值对应的是哪两个节点也标记出来了)。
如果大家不理解,可以跟着我们下面的讲解,看 minDist数组的变化 minDist数组 里记录的权值对应的哪条边。
如果大家不理解可以跟着我们下面的讲解看minDist数组的变化minDist数组里记录的权值对应的哪条边。
理解这一点很重要,因为 最后我们要求 最小生成树里所有边的权值和。
理解这一点很重要,因为最后我们要求最小生成树里所有边的权值和。
2、prim三部曲第二步最近节点加入生成树
2、prim三部曲第二步最近节点加入生成树
此时 节点1、节点2、节点3、节点4 算是 最小生成树的节点。
此时节点1、节点2、节点3、节点4算是最小生成树的节点。
3、prim三部曲第三步更新非生成树节点到生成树的距离即更新minDist数组
接下来更新节点距离最小生成树的距离,如图:
接下来更新节点距离最小生成树的距离,如图:
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102618.png)
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102618.png)
minDist数组已经更新了 所有非生成树的节点距离 最小生成树节点1、节点2、节点3、节点4 )的距离
minDist数组已经更新了所有非生成树的节点距离最小生成树节点1、节点2、节点3、节点4的距离
* 节点 5 和 节点 4的距离为 1和原先的距离值 2 所以更新minDist[5]为1。
* 节点5和节点4的距离为1和原先的距离值2所以更新minDist[5]为1。
### 6
### 6
1、prim三部曲第一步选距离生成树最近节点
继续选距离 最小生成树节点1、节点2、节点3、节点4 )最近的非生成树里的节点,只有 节点 5 和 节点6。
继续选距离最小生成树节点1、节点2、节点3、节点4最近的非生成树里的节点只有节点5和节点6。
选节点5 选节点6也可以加入 生成树。
选节点5选节点6也可以加入生成树。
2、prim三部曲第二步最近节点加入生成树
2、prim三部曲第二步最近节点加入生成树
节点1、节点2、节点3、节点4、节点5 算是 最小生成树的节点。
节点1、节点2、节点3、节点4、节点5算是最小生成树的节点。
3、prim三部曲第三步更新非生成树节点到生成树的距离即更新minDist数组
@ -234,44 +234,44 @@ minDist数组已经更新了 所有非生成树的节点距离 最小生成树
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102646.png)
minDist数组已经更新了 所有非生成树的节点距离 最小生成树节点1、节点2、节点3、节点4 、节点5的距离
minDist数组已经更新了所有非生成树的节点距离最小生成树节点1、节点2、节点3、节点4、节点5的距离
* 节点 6 和 节点 5 距离为 2比原先的距离值 1 大,所以不更新
* 节点 7 和 节点 5 距离为 1比原先的距离值 10001小更新 minDist[7]
* 节点6和节点5距离为2比原先的距离值1大,所以不更新
* 节点7和节点5距离为1比原先的距离值10001小更新minDist[7]
### 7
### 7
1、prim三部曲第一步选距离生成树最近节点
继续选距离 最小生成树节点1、节点2、节点3、节点4 、节点5最近的非生成树里的节点只有 节点 6 和 节点7。
继续选距离最小生成树节点1、节点2、节点3、节点4、节点5最近的非生成树里的节点只有节点6和节点7。
2、prim三部曲第二步最近节点加入生成树
2、prim三部曲第二步最近节点加入生成树
选节点6 选节点7也行距离一样的加入生成树。
选节点6选节点7也行距离一样的加入生成树。
3、prim三部曲第三步更新非生成树节点到生成树的距离即更新minDist数组
节点1、节点2、节点3、节点4、节点5、节点6 算是 最小生成树的节点 ,接下来更新节点距离最小生成树的距离,如图:
节点1、节点2、节点3、节点4、节点5、节点6算是最小生成树的节点接下来更新节点距离最小生成树的距离如图
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102732.png)
这里就不在重复描述了大家类推最后节点7加入生成树如图
这里就不在重复描述了大家类推最后节点7加入生成树如图
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102820.png)
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102820.png)
### 最后
### 最后
最后我们就生成了一个 最小生成树, 绿色的边将所有节点链接到一起,并且 保证权值是最小的,因为我们在更新 minDist 数组的时候,都是选距离 最小生成树最近的点 加入到树中。
最后我们就生成了一个最小生成树绿色的边将所有节点链接到一起并且保证权值是最小的因为我们在更新minDist数组的时候都是选距离最小生成树最近的点加入到树中。
讲解上面的模拟过程的时候,我已经强调多次 minDist数组 是记录了 所有非生成树节点距离生成树的最小距离。
讲解上面的模拟过程的时候我已经强调多次minDist数组是记录了所有非生成树节点距离生成树的最小距离。
最后minDist数组 也就是记录的是最小生成树所有边的权值。
最后minDist数组也就是记录的是最小生成树所有边的权值。
我在图中,特别把 每条边的权值对应的是哪两个节点 标记出来例如minDist[7] = 1对应的是节点5节点7之间的边而不是 节点6节点7为了就是让大家清楚 minDist里的每一个值 对应的是哪条边。
我在图中特别把每条边的权值对应的是哪两个节点标记出来例如minDist[7]=1对应的是节点5节点7之间的边而不是节点6节点7为了就是让大家清楚minDist里的每一个值对应的是哪条边。
那么我们要求最小生成树里边的权值总和 就是最后的 minDist 数组 累加一起。
那么我们要求最小生成树里边的权值总和就是最后的minDist数组累加一起。
以下代码,我对 prim三部曲做了重点注释大家根据这三步就可以 透彻理解prim。
以下代码我对prim三部曲做了重点注释大家根据这三步就可以透彻理解prim。
```CPP
#include<iostream>
@ -338,52 +338,52 @@ int main() {
}
```
```
时间复杂度为 O(n^2),其中 n 为节点数量。
时间复杂度为O(n^2),其中n为节点数量。
## 拓展
上面讲解的是记录了最小生成树 所有边的权值,如果让打印出来 最小生成树的每条边呢? 或者说 要把这个最小生成树画出来呢?
上面讲解的是记录了最小生成树所有边的权值,如果让打印出来最小生成树的每条边呢?或者说要把这个最小生成树画出来呢?
此时我们就需要把 最小生成树里每一条边记录下来。
此时我们就需要把最小生成树里每一条边记录下来。
此时有两个问题:
此时有两个问题:
* 1、用什么结构来记录
* 2、如何记录
* 1、用什么结构来记录
* 2、如何记录
如果记录边,其实就是记录两个节点就可以,两个节点连成一条边。
如果记录边,其实就是记录两个节点就可以,两个节点连成一条边。
如何记录两个节点呢?
我们使用一维数组就可以记录。 parent[节点编号] = 节点编号, 这样就把一条边记录下来了。当然如果节点编号非常大可以考虑使用map
我们使用一维数组就可以记录。parent[节点编号] = 节点编号这样就把一条边记录下来了。当然如果节点编号非常大可以考虑使用map
使用一维数组记录是有向边,不过我们这里不需要记录方向,所以只关注两条边是连接的就行。
使用一维数组记录是有向边,不过我们这里不需要记录方向,所以只关注两条边是连接的就行。
parent数组初始化代码
parent数组初始化代码
```CPP
vector<int> parent(v + 1, -1);
```
接下来就是第二个问题,如何记录?
接下来就是第二个问题,如何记录?
我们再来回顾一下 prim三部曲
我们再来回顾一下prim三部曲
1. 第一步,选距离生成树最近节点
2. 第二步,最近节点加入生成树
2. 第二步,最近节点加入生成树
3. 第三步更新非生成树节点到生成树的距离即更新minDist数组
大家先思考一下,我们是在第几步,可以记录 最小生成树的边呢?
大家先思考一下,我们是在第几步,可以记录最小生成树的边呢?
在本面上半篇 我们讲解过:“我们根据 minDist数组选组距离 生成树 最近的节点 加入生成树,那么 **minDist数组里记录的其实也是 最小生成树的边的权值**。”
在本面上半篇我们讲解过“我们根据minDist数组选组距离生成树最近的节点加入生成树那么**minDist数组里记录的其实也是最小生成树的边的权值**。”
既然 minDist数组 记录了 最小生成树的边,是不是就是在更新 minDist数组 的时候去更新parent数组来记录一下对应的边呢。
既然minDist数组记录了最小生成树的边是不是就是在更新minDist数组的时候去更新parent数组来记录一下对应的边呢。
所以 在 prim三部曲中的第三步更新 parent数组代码如下
所以在prim三部曲中的第三步更新parent数组代码如下
```CPP
for (int j = 1; j <= v; j++) {
@ -394,23 +394,23 @@ for (int j = 1; j <= v; j++) {
}
```
代码中注释中,我强调了 数组指向的顺序很重要。 因为不少录友在这里会写成这样: `parent[cur] = j`
代码中注释中,我强调了数组指向的顺序很重要。因为不少录友在这里会写成这样: `parent[cur] = j` 。
这里估计大家会疑惑了parent[节点编号A] = 节点编号B 就表示A 和 B 相连,我们这里就不用在意方向,代码中 为什么 只能 `parent[j] = cur` 而不能 `parent[cur] = j` 这么写呢?
这里估计大家会疑惑了parent[节点编号A] = 节点编号B就表示A和B相连,我们这里就不用在意方向,代码中为什么只能 `parent[j] = cur` 而不能 `parent[cur] = j` 这么写呢?
如果写成 `parent[cur] = j`,在 for 循环中,有多个 j 满足要求, 那么 parent[cur] 就会被反复覆盖,因为 cur 是一个固定值。
如果写成 `parent[cur] = j`在for循环中有多个j满足要求,那么 parent[cur] 就会被反复覆盖因为cur是一个固定值。
举个例子cur = 1for循环中可能 就 j = 2 j = 3j =4 都符合条件,那么本来应该记录 节点1节点 2、节点3、节点4相连的。
举个例子cur=1for循环中可能就j=2j=3j=4都符合条件那么本来应该记录节点1节点2、节点3、节点4相连的。
如果 `parent[cur] = j` 这么写,最后更新的逻辑是 parent[1] = 2, parent[1] = 3 parent[1] = 4 最后只能记录 节点1 与节点 4 相连,其他相连情况都被覆盖了。
如果 `parent[cur] = j` 这么写,最后更新的逻辑是 parent[1] = 2, parent[1] = 3 parent[1] = 4最后只能记录节点1与节点4相连,其他相连情况都被覆盖了。
如果这么写 `parent[j] = cur` 那就是 parent[2] = 1, parent[3] = 1 parent[4] = 1 ,这样 才能完整表示出 节点1其他节点都是链接的,才没有被覆盖。
如果这么写 `parent[j] = cur`那就是 parent[2] = 1, parent[3] = 1 parent[4] = 1 这样才能完整表示出节点1其他节点都是链接的,才没有被覆盖。
主要问题也是我们使用了一维数组来记录。
如果是二维数组,来记录两个点链接,例如 parent[节点编号A][节点编号B] = 1 parent[节点编号B][节点编号A] = 1来表示 节点A节点B 相连,那就没有上面说的这个注意事项了,当然这么做的话,就是多开辟的内存空间。
如果是二维数组,来记录两个点链接,例如 parent[节点编号A][节点编号B] = 1 parent[节点编号B][节点编号A] = 1来表示节点A节点B相连那就没有上面说的这个注意事项了当然这么做的话就是多开辟的内存空间。
以下是输出最小生成树边的代码,不算最后输出, 就额外添加了两行代码,我都注释标记了:
以下是输出最小生成树边的代码,不算最后输出,就额外添加了两行代码,我都注释标记了:
```CPP
#include<iostream>
@ -460,7 +460,7 @@ int main() {
}
}
```
```
按照本题示例,代码输入如下:
@ -476,40 +476,40 @@ int main() {
注意,这里是无向图,我在输出上添加了箭头仅仅是为了方便大家看出是边的意思。
大家可以和我们本题最后生成的最小生成树的图 去对比一下 边的链接情况:
大家可以和我们本题最后生成的最小生成树的图去对比一下边的链接情况:
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231229115714.png)
绿色的边 是最小生成树,和我们的 输出完全一致。
绿色的边是最小生成树,和我们的输出完全一致。
## 总结
## 总结
此时我就把prim算法讲解完毕了我们再来回顾一下。
此时我就把prim算法讲解完毕了我们再来回顾一下。
关于 prim算法我自创了三部曲来帮助大家理解
关于prim算法我自创了三部曲来帮助大家理解
1. 第一步,选距离生成树最近节点
2. 第二步,最近节点加入生成树
2. 第二步,最近节点加入生成树
3. 第三步更新非生成树节点到生成树的距离即更新minDist数组
大家只要理解这三部曲, prim算法 至少是可以写出一个框架出来,然后在慢慢补充细节,这样不至于 自己在写prim的时候 两眼一抹黑 完全凭感觉去写。
这也为什么很多录友感觉 prim算法比较难而且每次学会来隔一段时间 又不会写了,主要是 没有一个纲领。
大家只要理解这三部曲prim算法至少是可以写出一个框架出来然后在慢慢补充细节这样不至于自己在写prim的时候两眼一抹黑完全凭感觉去写。
这也为什么很多录友感觉prim算法比较难而且每次学会来隔一段时间又不会写了主要是没有一个纲领。
理解这三部曲之后,更重要的 就是理解 minDist数组。
理解这三部曲之后更重要的就是理解minDist数组。
**minDist数组 是prim算法的灵魂它帮助 prim算法完成最重要的一步就是如何找到 距离最小生成树最近的点**。
**minDist数组是prim算法的灵魂它帮助prim算法完成最重要的一步就是如何找到距离最小生成树最近的点**。
再来帮大家回顾 minDist数组 的含义:记录 每一个节点距离最小生成树的最近距离。
再来帮大家回顾minDist数组的含义记录每一个节点距离最小生成树的最近距离。
理解 minDist数组 至少大家看prim算法的代码不会懵。
理解minDist数组至少大家看prim算法的代码不会懵。
也正是 因为 minDist数组 的作用,我们根据 minDist数组选取距离 生成树 最近的节点 加入生成树,那么 **minDist数组里记录的其实也是 最小生成树的边的权值**。
也正是因为minDist数组的作用我们根据minDist数组选取距离生成树最近的节点加入生成树那么**minDist数组里记录的其实也是最小生成树的边的权值**。
所以我们求 最小生成树的权值和 就是 计算后的 minDist数组 数值总和。
所以我们求最小生成树的权值和就是计算后的minDist数组数值总和。
最后我们拓展了如何求职 最小生成树 的每一条边,其实 添加的代码很简单,主要是理解 为什么使用 parent数组 来记录边 以及 在哪里 更新parent数组。
最后我们拓展了如何获得最小生成树的每一条边其实添加的代码很简单主要是理解为什么使用parent数组来记录边以及在哪里更新parent数组。
同时,因为使用一维数组,数组的下标和数组 如何赋值很重要,不要搞反,导致结果被覆盖。
同时,因为使用一维数组,数组的下标和数组如何赋值很重要,不要搞反,导致结果被覆盖。
好了,以上为总结,录友们学习愉快。