您的位置:首页 > 其它

Prim最小生成树算法

2015-06-12 20:12 197 查看

Prim 算法

主要要解决问题

1、 尽可能选取权值小的边,但不能构成回路;

2、 选取n-1条恰当的边以连通n个顶点;


prim

MST性质:假设G=(V,E)是一个连通网,U是顶点V的一个非空子集。若(u,v)是一条具有最小权值的边,其中u∈U,v∈V-U,则必存在一棵包含边(u,v)的最小生成树。

算法基本思想:

假设G=(V,E)是连通的,TE是G上最小生成树中边的集合。算法从U={u0}(u0∈V)、TE={}开始。重复执行下列操作:

在所有u∈U,v∈V-U的边(u,v)∈E中找一条权值最小的边(u0,v0)并入集合TE中,同时v0并入U,直到V=U为止。此时,TE中必有n-1条边,T=(V,TE)为G的最小生成树。

Prim算法的核心:始终保持TE中的边集构成一棵生成树。

注意:prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边得数目无关,而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图。

算法思想类似于迪杰斯特拉算法

以下代码来自于nocow:

const int N=500;
unsigned long D
,Q

;//邻接阵表示距离,无边时此值为4294967295
bool cmp(int x,int y){return D[x]<D[y];}
unsigned long Prim(void){
int i=N;
list<int>L;
for(memcpy(D,Q[0],sizeof(D));
--i;
L.push_back(i));//以0号点为基准,L为还未进入最小生成树的点之集合

for(list<int>::iterator p;!L.empty();)//找到能见到的最短边,将新点从L中除去,然后以新点为基准,更新L中剩余点,直到L为空

for(p=min_element(L.begin(),L.end(),cmp),i=*p,L.erase(p),p=L.end();
L.end()!=++p;
D[*p]<?=Q[i][*p]);
return  accumulate(1+D,N+D,0LU);//对D求和,即为最小生成树总长
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM学习笔记