Prim最小生成树算法

来源:互联网 发布:肥皂水灌肠的浓度算法 编辑:程序博客网 时间:2024/06/05 17:10

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[N],Q[N][N];//邻接阵表示距离,无边时此值为4294967295bool 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求和,即为最小生成树总长}
0 0
原创粉丝点击