AcWing 858. 超详细Prim算法题解!
原题链接
简单
作者:
moodyy
,
2024-11-27 14:07:22
,
所有人可见
,
阅读 2
#include <iostream>
#include <cstring>
using namespace std;
const int N = 510;
bool st[N];
int g[N][N];//稠密图的最小生成树-Prim算法,稠密图用邻接矩阵存储
int dist[N];//dist表示点到集合的距离(点到集合的最短边长)
int n, m;
int Prim()
{
int res = 0;
memset(dist, 0x3f, sizeof dist), dist[1] = 0;
//Prim算法:每次迭代找到距离集合最近的点,也就是找到离集合的边最短的点
//找到这个点之后,用这个点去更新其他点到集合的距离,和Dijkstra很像
for (int i = 0; i < n; i ++) //迭代n次,因为最小生成树有n个点
{
//首先找到“到集合距离最短的点”
int t = 0; //用t记录这个点,初始化为-1和0都行,初始化为-1的话if里面要加个特判
for (int j = 1; j <= n; j ++)
if (!st[j] && dist[j] < dist[t])
t = j;
//更新一下最小生成树集合(这里的最小生成树是局部的,当迭代n此后就是整体的最小生成树)
res += dist[t];
st[t] = true;
//用t到集合的最短距离更新其他点
for (int k = 1; k <= n; k ++)
//因为t是最新的到集合最短的点,t和k间的距离如果小于原来的“k到集合的距离”,就更新
dist[k] = min(dist[k],g[t][k]);
}
return res;
}
int main()
{
memset(g, 0x3f, sizeof g); //一定要初始化为无穷大,不然处理重边的时候g会恒为0
cin >> n >> m;
while (m --)
{
int a, b, c;
cin >> a >> b >> c;
//最小生成树要求不能有自环,所以要处理自环
if (a == b) continue;
else g[a][b] = g[b][a] = min(g[a][b], c); // 处理重边
}
int ret = Prim();
//一定不要忘记判断这个!因为可能有闭合回路以及负环回路!
//闭合回路对应路径不通,应该是正无穷,但是有负权边,所以用 > 0x3f3f3f3f/2判断
//因为有负环回路,所以路径可能会是负无穷,所以用 < -0x3f3f3f3f/2判断
if (ret > 0x3f3f3f3f/2 || ret < -0x3f3f3f3f / 2) puts("impossible");
else printf("%d\n",ret);
return 0;
}