我们假设目前得到了一颗树为T,且是有最小权值的,T中的顶点集合为X,然后我们贪心的选取X之外的顶点和T相连的拥有最小权值的边,并把它加到T中,不断进行这个操作,当X=V时,就可以得到一颗生成树,我们可以证明,这棵树就是最小生成树,具体的证明方法这里不再累述(反证法)。
代码如下:
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
const int maxv=100;
const int inf=99999;
bool used[maxv]; //是否属于集合X
int mincost[maxv]; //从集合X出发的边到每个顶点的最小权值
int weight[maxv][maxv]; //每条边的权重
int n,m; //n vertexs,{1,2,3...n}, m edges.
int prim()
{
memset(used,0,sizeof(used));
for(int i=1;i<=n;i++) mincost[i]=inf;
mincost[1]=0; //从顶点编号为1 的顶点开始
int res=0;
while(1)
{
int index=-1;
for(int u=1;u<=n;u++) //从不属于集合X的顶点中选取从X到其权值最小的顶点
{
if(!used[u] && (index==-1 || mincost[u]<mincost[index]))
index=u;
}
if(index==-1)break;
used[index]=1;
res+=mincost[index];
for(int u=1;u<=n;u++){
mincost[u]=min(mincost[u],weight[index][u]);
}
}
return res;
}
int main()
{
while(cin>>n>>m)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
weight[i][j]=inf;
for(int i=0;i<m;i++)
{
int u,v,c;
cin>>u>>v>>c;
weight[u][v]=c;
weight[v][u]=c;
}
cout<<prim()<<endl;
}
}
给出一组测试实例:
7 9
1 2 1
2 3 2
2 4 3
2 6 7
3 5 10
5 6 5
6 7 8
4 6 1
4 7 5
输出结果:17