最小生成树贪心算法

一、引入:

1、生成树: 所有顶点均由边连接在一起,但不存在回路的图

最小生成树(Minimum Spanning Tree) 即权值和最小的生成树。

2、MST性质Minimum Spanning Tree)
在这里插入图片描述
二、Prim算法

算法思路:
首先就是从图中的一个起点a(这里假设是1)开始,把a加入U集合,然后,寻找从与a有关联的边中,权重最小的那条边并且该边的终点b(这里是3)在顶点集合:(V-U)中,我们也把b(3)加入到集合U中,并且输出边(a,b)的信息,这样我们的集合U就有:{a,b},然后,我们寻找与a关联和b关联的边中,权重最小的那条边并且该边的终点在集合:(V-U)中,我们把c(6)加入到集合U中,并且输出对应的那条边的信息,这样我们的集合U就有:{a,b,c}这三个元素了,一次类推,直到所有顶点都加入到了集合U。

在这里插入图片描述

(选边过程)

完整代码如下:

#include <iostream>
using namespace std;

const int N = 6;
#define INF 0x3f3f3f3f  //无穷大
int c[N + 1][N + 1] = {{0},
                       {0, INF, 6, 1, 5, INF, INF},
                       {0, 6, INF, 5, INF, 3, INF},
                       {0, 1, 5, INF, 5, 6, 4},
                       {0, 5, INF, 5, INF, 5, 2},
                       {0, INF, 3, 6, INF, INF, 6},
                       {0, INF, INF, 4, 2, 6, INF}

};

void Prim(int n) {
  int lowcost[N + 1];  //记录c[j][closest]的最小权值
  int closet[N + 1];   // V-S中点j在S中的最邻接顶点
  bool s[N + 1];
  s[1] = true;  //选择1作为起点

  //初始化s[i],lowcost[i],closest[i]
  for (int i = 2; i <= n; i++) {
    lowcost[i] = c[1][i];
    closet[i] = 1;
    s[i] = false;
  }

  for (int i = 1; i < n; i++) {
    int min = INF;
    int j = 1;  //邻接点
    for (int k = 2; k <= n; k++) {
      //找出V-S中使lowcost最小的顶点j
      if (lowcost[k] < min && !s[k]) {
        min = lowcost[k];
        j = k;
      }
    }
    cout << j << " " << closet[j] << endl;
    s[j] = true;  //将j添加到S中

    for (int k = 2; k <= n; k++) {
      //将j添加到S中后,修改closest和lowcost的值
      if (c[j][k] < lowcost[k] && !s[k]) {
        lowcost[k] = c[j][k];
        closet[k] = j;
      }
    }
  }
}

int main() {
  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= N; j++) {
      if (c[i][j] != INF)
        cout << c[i][j] << "\t";
      else
        cout << "∞\t";
    }
    cout << endl;
  }
  cout << "Prim选边过程为:" << endl;
  Prim(N);
  return 0;
}

在这里插入图片描述

三、kruskal算法

1、基本思想:
首先将G的n个顶点看成n个孤立的连通分支,将所有的边按权从小到大排序;然后从第一条边开始,依边权递增的顺序查看每条边,并按下述方法连接两个不同的连通分支:

  • 当查看到第k条边(v,w)时,如果端点v和w分别是当前两个不同的连通分支T1和T2中的顶点时,就用边(v,w)将T1和T2连接成一个连通分支,然后继续查看第k+1条边;
  • 如果端点v和w在当前的同一个连通分支中,就直接再查看第k+1条边。

这个过程一直进行到只剩下一个连通分支时为止。此时,这个连通分支就是G的一颗最小生成树。

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值