克鲁斯卡尔算法求解最小生成树

本文介绍如何使用克鲁斯卡尔算法求解图的最小生成树问题。通过初始化节点值,按照边的权重排序,寻找节点的祖先来避免回路,最终构建最小生成树并返回总权重。
摘要由CSDN通过智能技术生成
Kruskal 算法
出发点 :要使 生成树上边的权值之和达到最小,则应 使其中 每一条边的权值尽可能地小
具体步骤

         对于图 (V, E),有N个节点,求解最小生成树 TE

1. 构造一个只含 N 顶点的子图 SG
2. 找到一条权值最小的边 e ,若加入 e 能是 SG 不构成回路,则加上边 e SG
3. 重复操作 2 ,次数为 N-1

 

 

#include <iostream>
#include <string.h>
#include <vector>
#include <algorithm>

using namespace std;

const int MAX_NUM = 100;

typedef struct Edge{
 int point1;  /* 边的端点1 */
 int point2;  /* 边的端点2 */
 int weight;  /*边的权值*/
} Edge;

Edge edge[MAX_NUM]; /* 存储边*/
int node[MAX_NUM];  /*存储对应顶点的祖先*/

bool cmp(const Edge &e1, const Edge &e2)
{
 return e1.weight < e2.weight;
}

/* 寻找节点x的祖先
例如node[2]=1 node[8]=1 ,node[3]=1,
共同的祖先是1, 如果此时加入边(3,8)加进去,则构成回路,
不能加入到最小生成树中*/
int find(int x)
{
 return node[x] == x ? x : node[x] = find(node[x]);
}

int kruskal(int N, int E) /*N: 顶点数E:边数*/
{
 int ret = 0;
 int count = 0;

 /*初始化node值为序号*/
 for(int i = 0; i < E; i++)
  node[i] = i;

 /*按照weight值从小到大排序*/
 sort(edge, edge+E, cmp);

 for(int i = 0; i < E; i++) {
  int x = find(edge[i].point1);
  int y = find(edge[i].point2);
  /*如果x==y,则表明他们有共同的祖先,会构成回路,进行下一次迭代*/
  if(x != y) {
   /* 叠加weight到结果值ret中,并更新node值
   此处即为TE的生成过程,如果想要知道详细路径可以在此记录 */
   ret += edge[i].weight;
   if (x < y) {
    node[x] = y;
   } else {
    node[y] = x;
   }
  }

  /*迭代次数达标,已经产生了N-1条边,构成了最小生成树*/
  if (count == N-1)
   break;
 }

 return ret;
}

int main()
{
 memset(node, 0, sizeof(node));
 memset(edge, 0, sizeof(edge));

 int N; /*顶点数*/
 int E; /*边数*/
 cin >> N;
 cin >> E;
 for (int i = 0; i < E; ++i) {
  cin >> edge[i].point1;
  cin >> edge[i].point2;
  cin >> edge[i].weight;
 }

 cout << kruskal(E) << endl;

 return 0;
}


 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值