acwing858 Prim算法求最小生成树(模板)
prim算法时间复杂度为o(n^2)
prim的dijkstra的不同在于点更新距离时
prim是点到集合距离,dijkstra是点到起点的距离
伪代码
res记录最小生成树的边权和,st[] 记录该点是否在集合内,初始化dist[] 记录该点到集合最近距离 st记录随机一个点到集合,(一般是1) for 更新所有点到"集合"最短距离 for n-1次 for 循环点,找到集合外距离"集合"最近的点t st记录t加入集合 res加上t的最短距离dist[t] if (最短的距离dist[t]为INF )return INF 说明不是连通图,无最小生成树 for 更新"集合"外的点到集合距离 return res板子:
#include <bits/stdc++.h>
using namespace std;
int n,m,a,b,c;
const int N=505;
int g[N][N],dist[N];
bool st[N];//状态,是否在集合里
int prim(){
int res=0;
memset(dist,0x3f,sizeof dist);
st[1]=true;
for(int i=2;i<=n;i++) dist[i]=min(dist[i],g[1][i]);
for(int i=0;i<n-1;i++){
int t=-1;
for(int j=1;j<=n;j++){
if(!st[j]&&(t==-1||dist[j]<dist[t])) t=j;
}
st[t]=true;
res+=dist[t];
if(dist[t]>0x3f3f3f3f/2) return 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--){
scanf("%d%d%d",&a,&b,&c);
g[a][b]=g[b][a]=min(g[a][b],c);
}
int ans=prim();
if(ans>0x3f3f3f3f/2) puts("impossible");
else printf("%d\n",ans);
return 0;
} prim函数的稍微简便写法 int prim(){
int res=0;
memset(dist,0x3f,sizeof dist);
for(int i=0;i<n;i++){//集合初始为空的情况也考虑进
int t=-1;
for(int j=1;j<=n;j++){
if(!st[j]&&(t==-1||dist[j]<dist[t])) t=j;
}
st[t]=true;
if(i) res+=dist[t];
if(i&&dist[t]>0x3f3f3f3f/2) return dist[t];
for(int j=1;j<=n;j++) dist[j]=min(dist[j],g[t][j]);
}
return res;
}
查看8道真题和解析