最小生成树之Prim算法
普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。
算法思想:
1) .输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
3).重复下列操作,直到Vnew = V:
a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,在顶点集合V中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。
图例说明:
原图:
第一步:找一个A点,找与A点距离最短的点C,<A,C>为1,连接
第二步:找与A,C距离最近的点且连接没有回路的点,为F,<C,F>为4,连接
第三步:找与A,C,F距离最近的点且连接没有回路的点,为D,<F,D>为2,连接
第四步:找与A,C,F,D距离最近的点且连接没有回路的点,为B,<C,B>为5,连接
第五步:找与A,B,C,F距离最近的点且连接没有回路的点,为E,<B,E>为3,连接
时间复杂度:
Prim的时间复杂度为O(n*n),与网中的边数无关,因此适用于求变稠密的网的最小生成树
代码如下:
int Prim(int k)
{int v[1005];//保存点
int b[1005]://保存最短路径
memset(v,0,sizeof(v));
v[k]=1;
for(int i=1;i<=n;i++)
b[i]=a[k][i];
b[k]=0;
int sum=0,l;
for(int i=1;i<n;i++)
{
int max=0x3f3f;
for(int j=1;j<=n;j++)
{
if(!v[j]&&b[j]<max) //求当前最短路径
{
l=j; //求当前最短路径的点
max=b[j];
}
}
if(!v[l])
sum+=b[l]; //求出当前最短路径后加在一起
v[l]=1; //保存当前的点
for(int j=1;j<=n;j++)
{
if(!v[j]&&b[j]>a[l][j]) //更新
b[j]=a[l][j];
}
}
return sum;
}