//最小生成树的Prim算法:
//**最小生成树的一些性质:如果有n个节点,只需要n-1条边就可以连通。最小生成树就是从n(n-1)/2条边中找到最小代价的n-1条边
//1,利用了MST的性质:假如N=(V,{E})是一个连通网,U是顶点集V的一个非空的子集。
//若(u,v)是一条具有最小权值(代价)的边,其中u是U的元素,v是V-U的元素,则必存在一颗包含边(u,v)的最小生成树
//2,Prim算法的描述:
// 假如N=(V,{E})是连通网,TE是N上最小生成树中边得集合。算法从U={u0}(u0是V中的元素),TE={}开始,重复执行下述操作:
// 在所有u属于U,v属于V-U的边(u,v)属于E中找一条代价最小的边并入TE,同时把v0并入U,直到U=V为止。
//算法:
//一,**使用两个辅助数组:
// 1,(lowcost[i]存放从U集合到(V-U)集合中代价最小的边(lowxost>0)。如果同时如果i被加入U,则lowcost = -1.)
// 2,closedge[i]:当v并入U后,需要重新选择从U集合到(V-U)集合中选出代价最小的边(u,v),closedge[]就是记录最小代价边中节点u的一个数组。
//二,**算法实现:
// 1,把u(属于V)并入U,并对lowcost进行初始化。
// ***重复下面过程,直到U=V。
// 2,求最小代价边(从lowcast中找出最小代价边,并记录v)
// 3,把v并入U中。
// 4,v并入U后,重新计算从U集合到(V-U)集合中代价最小的边(u,v),并存入lowcaset中,同时记录closedge[i]。
#include<iostream>
#include<iomanip>
using namespace std;
int map[7][7] = {
{0 , 2 , 4 , 1 , 0 , 0 , 0 },
{2 , 0 , 0 , 3 , 10 , 0 , 0 },
{4 , 0 , 0 , 2 , 0 , 5 , 0 },
{1 , 3 , 2 , 0 , 7 , 8 , 4 },
{0 ,10 , 0 , 7 , 0 , 0 , 6 },
{0 , 0 , 5 , 8 , 0 , 0 , 1 },
{0 , 0 , 0 , 4 , 6 , 1 , 0 }
};
void Prim(int tree[7][7],int root)
{
int lowcost[7];
int closedge[7];
int n;
for(int i=0;i<7;++i) //locast初始化
if(i!=root)
{
lowcost[i]=map[root][i];
closedge[i]=root;
}
lowcost[root] = -1; //起点u0并入U
for(int j=0;j<7;++j) //重复--直到U==V
{
int min=100000;
for(i=0;i<7;++i) //求lowcast中最小代价边
if(lowcost[i]<min&& lowcost[i]>0)
{
min=lowcost[i];
n= i;
}
if(lowcost[n]!= -1) //记录最小生成树
{
tree[closedge[n]][n]=min;
tree[n][closedge[n]]=min;
}
lowcost[n] = -1; //v并入U
for(i=0;i<7;++i) //新顶点并入U后重新选择最小边
if(((map[n][i]<lowcost[i]) || (lowcost[i]==0)) && (map[n][i] >0))
{
lowcost[i]=map[n][i];
closedge[i]=n;
}
}
}
int main()
{
int tree[7][7] = {0};
Prim(tree,0);
for(int k=0; k!=7;++k)
{
for(int j=0;j!=7;++j)
cout<<setw(3)<<tree[k][j];
cout<<endl;
}
return 0;
}
最小生成树的Prim算法
最新推荐文章于 2024-10-08 12:54:42 发布