最小生成树(保证各个边权总和为最小值)因为学地图制图学的原因,可以应用于大规模的光缆建设以及道路建设,节约材料。也就是用最短的线连接个各个结点。
其实这个算法和Dijkstra算法确实有相似之处但绝对不一样。
看图:
Dijkstra算法:
从0开始向前走,那谁走远的路,自己去某一个城市旅行也是,地图上一看哪条路最近我就走哪条,走到哪个结点我就再看哪条路最短,所以Dijkstra常常用于解决最短路径问题。
Prim算法:
从0开始走,那条路短所以线就连到了1,然后我再比较1和7的路线哪一条更短,然后7就连接了6,6和1呢,我就再找到最小的,6连接到5,5再连接到2,2再连接到8,8已经到终点了,我再看剩余没有连接到的结点,谁最小,于是2又连接到3,3又连接到4。这样我就可以保证每一个结点都相连而且边权总和最小。
注意:
应该就能看出两种算法之间的区别了,就是Dijkstra到了另一个节点就不管之前的了,但是Prim就是还要看之前的找出结点把边权最小的找出来。
于是就是下图:
核心代码:
int prim(int m) {
memset(vis, false, sizeof(vis));
int index = m;
int sum = 0;
vis[index] = true;
for (int i = 0; i <n; i++) {
dis[i] = mp[index][i];
}
for (int i = 1; i <n; i++) {
int minx = inf;
for (int j = 0; j <n; j++) {//寻找最短的边到下一个结点
if (!vis[j] && dis[j] < minx) {
minx = dis[j];
index = j;
}
}
vis[index] = true;
sum += minx;
for (int j = 0; j <n; j++) {
if (!vis[j] && dis[j]>mp[index][j]) {判断哪一个结点的下一条边权最短
dis[j] = mp[index][j];
}
}
}
return sum;
}
例题:
P3366 【模板】最小生成树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P3366用Prim模板写的,代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int inf = 1e10 + 10;
int n, m;
int x, y, r;
int mp[5010][5010];
int dis[5010];
bool vis[5010];
void prim() {
int sum = 0;
for (int i = 1; i < n; i++) {
int index = 0;
int minx = inf;
for (int j = 1; j <= n; j++) {
if (vis[j]==false && dis[j] < minx) {//寻找哪个结点是当前结点能够到达的最短路径结点
minx = dis[j];
index = j;
}
}
if (index == 0) {//不连通的话
cout << "orz" << endl;
return;
}
vis[index] = true;
sum += dis[index];//每个最小边权结点的边权值
for (int j = 1; j <= n; j++) {//判断哪个结点的下一个结点的边权值最小
if (vis[j]==false && dis[j] > mp[index][j]) {
dis[j] = mp[index][j];
}
}
}
cout << sum << endl;
}
int main()
{
memset(vis, false, sizeof(vis));
cin >> n >> m;
for (int i = 1; i <= n; i++) {
dis[i] = inf;
for (int j = 1; j <= n; j++) {
mp[i][j] = inf;
}
}
for (int i = 1; i <= m; i++) {
cin >> x >> y >> r;
mp[x][y] = min(mp[x][y], r);
mp[y][x] = min(mp[y][x], r);
}
for (int i = 1; i <= n; i++) {
dis[i] = min(dis[i], mp[1][i]);
dis[i] = min(dis[i], mp[i][1]);
}
vis[1] = true;
prim();
}
Prim算法就暂时先介绍到这里,马上开始Kruskal算法篇。