858.Prim算法求最小生成树
题目描述
给定一个n个点m条边的无向图,图中可能存在重边和自环,边权可能为负数。求最小生成树的树边权重之和,如
果最小生成树不存在则输出impossible。
给定一张边带权的无向图G=(V,E),其中V表示图中点的集合,E表示图中边的集合,n=/V|,m=|E|。
第一行包含两个整数n和m。
输入格式
第一行包含两个整数n和m。
接下来m行,每行包含三个整数u,v,w,表示点u和点v之间存在一条权值为w的边。
输出格式
共一行,若存在最小生成树,则输出一个整数,表示最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。
数据范围
1 ≤ n ≤ 500,
1 ≤ m ≤ 10^5,
图中涉及边的边权的绝对值均不超过10000。
输入样式:
4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4
输出样式:
6
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 510, INF = 0x3f3f3f3f;
int n; // n表示点数
int g[N][N]; // 邻接矩阵,存储所有边
int dist[N]; // 存储其他点到当前最小生成树的距离
bool st[N]; // 存储每个点是否已经在生成树中
// 如果图不连通,则返回INF(值是0x3f3f3f3f), 否则返回最小生成树的树边权重之和
int prim()
{
memset(dist, 0x3f, sizeof dist); // 1、初始化dist为正无穷
int res = 0;
for (int i = 0; i < n; i ++ ) // 2、n次迭代,代表第i个加入的边
{
int t = -1;
for (int j = 1; j <= n; j ++ )
if (!st[j] && (t == -1 || dist[t] > dist[j])) // 3、找到集合外(!st[j])距离集合最近的点
t = j;
if (i && dist[t] == INF) return INF; // 如果不是第一条边且(当前距离集合最近的点,距离集合的距离是正无穷),所以不存在最小生成树
if (i) res += dist[t];
st[t] = true;
for (int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]); // 4、更新其他点到集合的距离
}
return res;
}
int main()
{
scanf("%d%d", &m, &m);
memset(g, 0x3f, sizeof g);
while(m -- )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
g[a][b] = g[b][a] = min(g[a][b], c);
}
int t = prim();
if(t == INF) puts("impossible");
else puts("%d\n", t);
return 0;
}