克鲁斯卡尔算法实现图的最小生成树(紫书)

过程如下:
对边集排序,选取最小的边
选取次小的边,判断是否形成环路,形成则舍去,不形成则选取,
重复以上步骤
(用并查集对节点集合快速合并,话说并查集真的是简单,暴力又优美啊//嘻嘻)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int u[200],v[200];//最大有200条边,每条边的两个节点的位置
float w[200];//每条边的权值
int f[200];//200个边的父节点,并查集使用
int node_num,side_num;//节点个数,边的个数
int r[200];//储存排序后,第小的边的编号
queue<int> side;
void build_map()//建立图
{
    int i;
    i = 0;
    printf("输入节点个数:\n");
    scanf("%d", &node_num);//输入节点个数
    printf("输入边的信息:节点1,节点2,权重 \n");
    while(1)
    {
        int a, b;
        float c;
        if (scanf("%d,%d,%f", &a, &b, &c) != 3) break;//输入该边的两个定点以及该边的权重
        u[i] = a;
        v[i] = b;
        w[i] = c;
        i++;
    }
    side_num = i;//统计边的个数
}
int cmp(int i, int j)
{
    return w[i] < w[j];
}
int find(int x)
//并查集,用于判断是否在同一个集合
//这是这些天遇到的第二个暴力,简洁,优美的算法了
{
    return f[x] == x ? x : find(f[x]);
}
int main()
{
    build_map();
    for (int i = 0; i < node_num; i++)
    {
        f[i] = i;//初始化并查集
    }
    for (int i = 0; i < side_num; i++)
    {
        r[i] = i;//初始化边的编号
    }
    sort(r, r + side_num, cmp);//对边按照顺序排列
    for (int i = 0; i < side_num; i++)
    {
        int k = r[i];
        int x = find(u[k]);
        int y = find(v[k]);
        if (x != y)//若两个节点不在同一个集合里,则合并
        {
            f[x] = y;
            side.push(r[i]);
        }
    }
    printf("边集为:\n");
    while (!side.empty())//输出边集
    {
        int m = side.front();
        side.pop();
        printf("%d,%d\n", u[m], v[m]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值