MSTkruskal算法的理解

来源:互联网 发布:在淘宝上买东西有技巧 编辑:程序博客网 时间:2024/05/17 23:34

伪代码:

把所有边排序,记第i小的边为e[i](1<=i<m)

初始化MST为空

初始化联通分量,让每个点自成一个独立的联通分量

for(int i = 0;i < m;i++)

if(e[i].u和e[i].v不在同一个联通分量)

{

把边e[i]加入MST

合并e[i].u和e[i].v的联通分量

}

首先把所有边按照权值排序,找到最小的权值所在的边,用这些点构造联通图可以保证图的权值最小。然后依次搜索,每次都找到下一个最小的点,如果这些点已经包含在联通图里,说明我们如果现在把它们放进去,图的权值会大于我们之前已经构建的图,不符合题意。所以只添加没有包含的点。如此扫描下去直到把所有点加进去,因为每个点加进去的都是最小权值,所以图的权值最小,也叫最小生成树(MST)

下一个关键问题是合并:合并的最简单表示方式是用并查集。用树表示集合。把点x的父节点保存在p[x]中(如果没有父节点,p[x]=x)。所以找出节点所在树的递归程序是:

int find(int x){p[x] == x?x:p = find(p[x]);}返回x所在的树根。

代码:int cmp(const int i,const int j){return w[i] < w[j];}//间接排序函数

int find(int x){return p[x] == x?x:p = find(p[x]);}//查找结点的树根

int Kurskal()

{

    int ans = 0;

    for(int i = 0;i < n;i++) p[i]=i;

    for(int i = 0;i < m;i++) r[i]=i;

    sort(r,r+m,cmp);

    for(int i = 0;i < m;i++)

      { int e=r[i];int x = find(u[e]);int y = find(v[e]);

       if(x != y){ans += w[e];p[x]=y;}//不在同一个集合,合并

    return ans;

}

0 0
原创粉丝点击