无向图的最小生成树
最小生成树
在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。
求最小生成树的两种方法
1.Kruskal算法
此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。
2.Prim算法
此算法可以称为“加点法”,每次迭代选择代价最小的边对应的点,加入到最小生成树中。算法从某一个顶点s开始,逐渐长大覆盖整个连通网的所有顶点。
第二种方法来实现代码,如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<algorithm> #include<string.h> using namespace std; int min;int n,m; int fan[10005][10005]; int vis[10005],low[10005]; int ss(){ int min,pos,sum=0; memset(vis,0,sizeof(vis)); pos=1; vis[1]=1; for(int i=1;i<=n;i++){ if(i!=pos) low[i]=fan[pos][i]; //此时的low[i]中找到了从点1开始到其他能联通边的权值 } for(int i=1;i<n;i++){ //共n-1条边相加 min=9999999; for(int j=1;j<=n;j++){ //按权值从小到大的顺序找边 if(!vis[j]&&low[j]<min){ //如果这个点没有被联通 min=low[j]; pos=j; } } sum+=min; //将权值大小依次相加。 vis[pos]=1;//标记一下表示此点已经和点1联通 for(int j=1;j<=n;j++){ //此时为找到和上一个点已经连通过的点,它和它能联通的点的边的权值 if(!vis[j]&&low[j]>fan[pos][j]){ low[j]=fan[pos][j]; } } } return sum; } int main(){ while(cin>>n>>m){ int a,b,c; memset(fan,999999,sizeof(fan)); for(int i=1;i<=m;i++){ cin>>a>>b>>c; if(fan[a][b]>c) { //防重边 fan[a][b]=c; fan[b][a]=c; } } cout<<ss()<<endl; } return 0; }