最小生成树算法分为
1.prime算法 O(n^2)
由点到边,每次将到集合距离最短的集合外的点加入集合中,在松弛集合外的点到集合的距离;
2.kruskal 0(mlogm)
将边从小到大排序,循环每一条边,如果两点未在同一集合里(并查集维护),则将该边加入集合中;
稠密图用prime,稀疏图用kruskal
prime
#include<iostream> #include<cstring> #include<queue> using namespace std; const int INF=0x3f3f3f3f; int n,m; int g[510][510]; int dist[510];int vis[510]; int prime() { memset(dist,0x3f,sizeof dist); int res=0; for(int i=0;i<n;i++)//迭代n次 { int t=-1; for(int j=1;j<=n;j++) if(!vis[j]&&(t==-1||dist[t]>dist[j])) t=j; if(i&&dist[t]==INF) return INF;//i如果不是第一个迭代且已经不存在最短边,则最小生成树不存在;‘ if(i)res+=dist[t];//如果不是第一次迭代则加入最小生成树的值 for(int j=1;j<=n;j++)dist[j]=min(dist[j],g[t][j]);//松弛到集合的距离 vis[t]=1; } return res; } int main() { memset(g,0x3f,sizeof g); cin>>n>>m; while(m--) { int a,b,c; cin>>a>>b>>c; g[a][b]=min(g[a][b],c); g[b][a]=min(g[b][a],c); } int t=prime(); if(t==0x3f3f3f3f)printf("impossible "); else printf("%d ",t); return 0; }
kruskal()
#include<iostream> #include<algorithm> using namespace std; int n,m; int p[200010]; struct node { int a,b,w; bool operator <(node &y)const { return w<y.w; } }edge[200010]; int find(int x) { if(p[x]==x)return x; else return p[x]=find(p[x]); } int main() { cin>>n>>m; for(int i=0;i<m;i++) { scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].w); } sort(edge,edge+m); for(int i=1;i<=n;i++) p[i]=i;int res=0,cnt=0;//cnt存加入集合的边数 for(int i=0;i<m;i++)//对每一条边操作 { int a=edge[i].a,b=edge[i].b,w=edge[i].w; a=find(a),b=find(b); if(a!=b) res+=w,p[a]=b,cnt++; } if(cnt<n-1)printf("impossible "); else printf("%d ",res); return 0; }