21xrx.com
2024-09-20 06:34:14 Friday
登录
文章检索 我的文章 写文章
C++邻接矩阵Kruskal算法求最小生成树
2023-07-11 15:00:15 深夜i     --     --
C++ 邻接矩阵 Kruskal算法 最小生成树

Kruskal算法是一种常用的求解最小生成树的算法之一。它的主要思想是从边集中按权值从小到大选取边,直至选出N-1条边为止,构成最小生成树。在C++语言中,我们可以使用邻接矩阵来实现Kruskal算法。

邻接矩阵是一种常用的图的表示方法,它通过一个二维数组来表示图中的顶点和边。我们可以将每个顶点看作一个数组下标,通过矩阵中的值来表示两个顶点之间是否连通。在Kruskal算法中,我们需要先建立一个无向带权图的邻接矩阵,然后按照边权值从小到大的顺序将边加入最小生成树中,当边的数量达到(N-1)时停止。

下面是Kruskal算法的具体实现:

1. 构造邻接矩阵并初始化为无穷大,表示两个点之间没有连线。

  int graph[MAX][MAX]; // MAX为矩阵的最大大小

  // 初始化邻接矩阵为无穷大

  for (int i = 0; i < MAX; i++) {

    for (int j = 0; j < MAX; j++) {

      graph[i][j] = INF; // INF为一个很大的数字

    }

  }

2. 输入边的数量和点的数量,并输入每条边和边的权重。

  int E, V; // E为边数,V为点数

  // 输入边和边权

  for (int i = 0; i < E; i++) {

    int u, v, w;

    cin >> u >> v >> w;

    graph[u][v] = w;

    graph[v][u] = w;

  }

3. 定义一个结构体来存储边的信息,并定义比较边权大小的函数。

  struct Edge v;

  bool cmp(Edge a, Edge b)

    return a.w < b.w;

4. 将边按照权重从小到大排序。

  Edge edges[MAX];

  int idx = 0;

  // 将边存入一个结构体数组中

  for (int i = 0; i < V; i++) {

    for (int j = i + 1; j < V; j++) {

      if (graph[i][j] != INF) {

        edges[idx].u = i;

        edges[idx].v = j;

        edges[idx].w = graph[i][j];

        idx++;

      }

    }

  }

  // 将边按照权重从小到大排序

  sort(edges, edges + idx, cmp);

5. 使用并查集来实现边的合并操作,直至树的大小为N-1。

  int parent[MAX];

  int rank[MAX];

  // 初始化并查集

  for (int i = 0; i < V; i++) {

    parent[i] = i; // 每个点的祖先为自身

    rank[i] = 0; // 初始秩为0

  }

  // 定义find函数,用来查找祖先

  int find(int x) {

    if (parent[x] == x) return x; // x为祖先,返回x

    else return parent[x] = find(parent[x]); // 继续向上查找,并进行路径压缩

  }

  // 定义union函数,用来合并两个点集

  void unite(int a, int b) {

    int pa = find(a), pb = find(b);

    if (rank[pa] < rank[pb]) parent[pa] = pb; // 将秩小的集合并入秩大的集合

    else if (rank[pa] > rank[pb]) parent[pb] = pa;

    else {

      parent[pa] = pb;

      rank[pb]++;

    }

  }

  int cnt = 0; // 记录加入的边数

  int ans = 0; // 记录最小生成树权重

  // 将边按照权重从小到大加入最小生成树中

  for (int i = 0; i < idx; i++) {

    if (find(edges[i].u) != find(edges[i].v)) {

      unite(edges[i].u, edges[i].v);

      ans += edges[i].w;

      cnt++;

      if (cnt == V - 1) break;

    }

  }

  cout << ans << endl;

通过以上代码,我们可以使用C++邻接矩阵Kruskal算法求解最小生成树。Kruskal算法的时间复杂度为O(ElogE),其中E为边数。在实际使用中,我们可以根据具体情况选择不同的算法来求解最小生成树,以保证程序的效率和精度。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复