淼淼Kruskal算法

应用场景:还是说建公路,电路网等如何缩短距离,减小成本。

算法过程:
运用了并查集的找祖先以及如何合并->

淼淼的并查集_钟一淼的博客-CSDN博客

 

主要还是看图示,kruskal算法一般会定义结构体

struct node{
    int x;
    int y;
    int side;//记录边权值
}
bool cmp(node x,node y){
    return x.side>y.side;
}

        首先看图,我们定义了这个结构体,然后进行排序,然后按最小的,找到最小边权值的两点连接1,3,然后继续寻找第二小的连接4,6,再找就是2连接5,3连接6,注意这边不能3连接4(因为会形成闭环),只要不形成闭环就按该顺序进行操作,操作n-1次即可。最后就走出到了最后一张图的位置,形成了一个最小生成树。

核心代码如下:

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
int father[N];
int find(int x) {//找祖先
    if (x == father[x]) {
        return x;
    }
    return find(father[x]);
}
struct node {
    int x, y, r;
}e[N*(N-1)*2];//最多有这么多的结点树上
bool cmp(node a, node b) {//按升序进行排列
    return a.r < b.r;
}
int main()
{
    int t;//t个测试数据
    int n;//n个结点
    for (int i = 1; i <= n; i++) {
        father[i] = i;
    }
    for (int i = 1; i <= n; i++) {
        cin >> e[i].x >> e[i].y >> e[i].r;
    }
    sort(e, e + n, cmp);
    int sum = 0;
    for (int i = 1; i <= n; i++) {
        int x = find(e[i].x);
        int y = find(e[i].y);
        if (x == y)continue;
        if (x != y) {//只要祖先不相同就不会形成闭环
            sum += e[i].r;
            father[x] = y;
        }
    }
    cout << sum << endl;
}

例题:

1584. 连接所有点的最小费用 - 力扣(LeetCode) (leetcode-cn.com)

题目分析:

1.单纯的一道模板题,定义结构体,排序,初始化(每个结点都是自己的祖先)给每个结点赋值,用公式求出边权值。

2.循环输入x,y ,判断祖先是不是一个(是一个就是闭环,排除),不是一个就合并成一个。最后输出边权值,即是最小边权值之和。

代码如下:

class Solution {
public:
    struct Node
    {
        int x, y, r;
    }e[1000100];//还是模板定义一个结构体
    static int cmp(Node a1, Node a2)
    {
        return a1.r < a2.r;//升序
    }
    int father[1010];
    int find(int x)//寻找祖先
    {
        if (x == father[x]) {
            return x;
        }
        return father[x] = find(father[x]);
    }
    int minCostConnectPoints(vector<vector<int>>& points) {
        int cnt = 0;
        for (int i = 0; i < points.size(); i++)
        {
            for (int j = i + 1; j < points.size(); j++)
            {
                e[cnt].x = i;
                e[cnt].y = j;
                e[cnt].r = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]);//符合公式求边权值
                cnt++;
            }
        }
        sort(e, e + cnt, cmp);//结构体排序
        for (int i = 0; i < points.size(); i++) {
            father[i] = i;
        }//初始化每个结点
        int ans = 0;
        for (int i = 0; i < cnt; i++)
        {
            int fx = find(e[i].x);
            int fy = find(e[i].y);
            if (fx != fy)
            {
                father[fx] = fy;//合并结点
                ans+= e[i].r;
            }
        }
        return ans;
    }
};

        kraskal算法的基础部分就这些了,还有部分优化部分请看后续。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钟一淼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值