您的位置:首页 > 其它

最小生成树——普里姆(Prim)算法

2017-02-17 22:25 218 查看
Prim算法的基本思想是以顶点为主导地位;从起始顶点出发,通过选择当前可用的最小权值的边把其他顶点加入到生成树中来。设连通无向网为G(V,E),在普里姆算法中,将顶点集合V分成两个子集T和T'.

(1)T:当前生成树顶点集合。

(2)T':不属于当前生成树的顶点集合

具体实现过程如下:(1)从连通无向网中选择一个起始顶点u0,首先将它加入到集合T中;然后选择与u0关联的,具有最小权值的边(u0,v),将顶点v加入到集合T中。

(2)以后每一步从一个顶点(设为u)在T中,而另一个顶点(设为v)在T'中的各条边中选择权值最小边(u,v),把顶点v加入到集合T中。如此继续,直到网络中的所有顶点都加入到生成树集合T中为止。

例题:利用prim()算法求下图中的最小生成树,并输出依次选择的各条边及最终求得的最小生成树的权值。



分析说明:

(1)lowcost[]:存放顶点集合T'内到顶点集合T内各顶点权值最小的边的权值

(2)nearvex[]:记录顶点集合T'内各顶点距离顶点集合T内哪个顶点最近;当nearvex[i]==-1时,表示顶点i属于顶点T.

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define maxint 0x3f3f3f
#define MAXN 110
int n,m;
int map[MAXN][MAXN];
int lowcost[MAXN];
int nearvex[MAXN];
void prim(int u0)
{
int i,j,min;
int sumweight=0;
for(i=1;i<=n;i++)
{
lowcost[i]=map[u0][i];
nearvex[i]=u0;
}
nearvex[u0]=-1;
for(i=1;i<n;i++)
{
min=maxint;
int v=-1;
for(j=1;j<=n;j++)
if(nearvex[j]!=-1&&lowcost[j]<min)///在没有加入集合T的各点中选取距离集合T最近的顶点
{
v=j;
min=lowcost[j];
}
if(v!=-1)///v==-1表示没有找到权值最小的边
{
printf("%d %d %d\n",nearvex[v],v,lowcost[v]);
nearvex[v]=-1;
sumweight+=lowcost[v];
for(j=1;j<=n;j++)
if(nearvex[j]!=-1&&map[v][j]<lowcost[j])///更新lowcost的权值
{
lowcost[j]=map[v][j];
nearvex[j]=v;///j距离集合T中的最近顶点改变
}
}
}
printf("weight of MST is %d\n",sumweight);
}
int main()
{
int i,j;
int u,v,w;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(map,maxint,sizeof(map));
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
map[u][v]=w;
map[v][u]=w;
}
prim(1);
}
return 0;
}




prim()算法的简化版(只是为了单纯的求最小生成树而已),代码如下

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define MAXN 30
#define maxint 0x3f3f3f3f
int map[MAXN][MAXN];
int n,m;
int visited[MAXN];
int lowcost[MAXN];
int prim()
{
int i,j;
int min,pos,sumweight=0;
memset(visited,0,sizeof(visited));
visited[1]=1;
pos=1;
for(i=1;i<=n;i++)
if(i!=pos)
lowcost[i]=map[pos][i];
for(i=1;i<n;i++)
{
min=maxint;
for(j=1;j<=n;j++)
if(visited[j]==0&&lowcost[j]<min)///在还没有访问的顶点中选择距离集合T最近的一个
{
min=lowcost[j];
pos=j;
}
sumweight+=min;
visited[pos]=1;
for(j=1;j<=n;j++)
if(visited[j]==0&&map[pos][j]<lowcost[j])///没有被访问的。更新lowcost的值
lowcost[j]=map[pos][j];
}
return sumweight;
}
int main()
{
int i,j;
int u,v,w;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(map,maxint,sizeof(map));
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
map[u][v]=w;
map[v][u]=w;
}
int ans=prim();
cout<<ans<<endl;
}
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: