前言
最小生成树问题常用的就两种算法,prim
和kruskal
。prim
适合稠密图,kruskal
适合稀疏图。
最小生成树问题的实际情况比如说,在n个村庄中修通道路,使得所有村庄都连通。
一、题目陈述
二、解决思路
- 设定一个集合
s
,s
是最小生成树包含的点的集合。初始化所有点到此集合的距离为无穷。 - 每次选择距离此集合最近的点加入集合中。利用这个点,更新所有集合外的点到集合的距离。点
a
到集合s
的距离定义为这个点到集合中所有点的距离的最小值。 - 直到所有的点都在集合
s
中。
三、代码实现
#include<iostream>
#include<cstring>
const int N = 510, INF=0x3f3f3f3f;
int n,m;
int g[N][N];
// 表示各个点到集合的距离
int dist[N];
// 表示集合s
bool st[N];
using namespace std;
int prim() {
memset(dist,0x3f,sizeof dist);
// 最小生成树边权之和
int res=0;
for(int i=0;i<n;i++) {
// t表示距离集合s最近的点
int t=-1;
for(int j=1;j<=n;j++) {
if(!st[j] && (t==-1||dist[t]>dist[j])) {
t = j;
}
}
// 不可能存在最小生成树
if(i && dist[t]==INF) return INF;
if(i) res += dist[t];
// 更新
for(int j=1;j<=n;j++) dist[j]=min(dist[j],g[t][j]);
st[t]=true;
}
return res;
}
int main() {
cin>>n>>m;
memset(g,0x3f,sizeof g);
for(int i=0;i<m;i++) {
int a,b,c; cin>>a>>b>>c;
// 处理重边
g[a][b]=g[b][a]=min(g[a][b],c);
}
int t = prim();
if(t==INF) puts("impossible");
else cout<<t<<endl;
return 0;
}
总结
记得先累积res再更新。