时间复杂度O(V^2)
算法思路:
- 随便选一个点作为起点(这里选点V1),让它加入到当前的集合。
- 搜索与当前集合距离最近的点,把它加入到我们的集合中
- 如果发现当前我们选到的点,距离我们的集合距离等于无穷,证明剩下的点也是等于无穷,不然算法也不会选一个无穷出来加入到我们的集合,此时直接返回错误,证明是不连通的
- 重复23步骤,直至所有点的已经加入到集合中。
手动计算时需要注意的点:
- 笔试中一般不会给不连通的图,需要注意不要把存在回路的边计算在内就好,因为加进来了就不是最小生成树了,最小生成树是极小不连通子图,不存在回路。
算法实现时需要注意的点
- 注意要加一个st状态判断数组,用来判断该点是否已经加入到集合中
- 注意初始化距离数组以及邻接矩阵
- 注意当挑选完一个新边之后,要判断一下他是否连通的。
代码:
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 510;
int g[N][N],dist[N];
bool st[N];
int n,m,res;
int prim(){
memset(dist,0x3f,sizeof dist);
dist[1] = 0; // 从点1开始
for(int i = 1; i <= n ; i++){
int t = -1; // 代表还没开始选点
for(int j = 1; j <= n ;j++){
if(!st[j] && (t==-1 || dist[j] < dist[t]))
t = j;
}
if(dist[t] == INF) return INF; //代表不连通
st[t] = true;
res += dist[t];
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 result = prim();
if(result == INF) cout << "impossible";
else cout << result;
return 0;
}