图论 Kruskal 最小生成树算法

news/2024/7/15 18:23:54 标签: 算法, 图论, 数据结构

前置知识

关于最小生成树

先说「树」和「图」的根本区别:树不会包含环,图可以包含环

树就是「无环连通图」

生成树是含有图中所有顶点的「无环连通子图」

你要保证这些边:

1、包含图中的所有节点。

2、形成的结构是树结构(即不存在环)。

3、权重和最小。

关于Union-Find

=> 作用:对树进行判定

对于添加的这条边,如果该边的两个节点本来就在同一连通分量里,那么添加这条边会产生环;

反之,如果该边的两个节点不在同一连通分量里,则添加这条边不会产生环

判断两个节点是否连通(是否在同一个连通分量中)就是 Union-Find 算法的拿手绝活

同一个连通分量就是有着共同父节点的一群结点


Kruskal算法

Kruskal算法就是在确保一些结点在一些边的关系下能构成树时执行贪心算法

说白了就是按照权重大小就是从小到大进行排序

connections里面的vector的前两项放的是结点,后面放的是权重

#include <bits/stdc++.h>
using namespace std;


class UF {
private:
    int count = 0; // 记录连通分量
    vector<int> parent; // 节点x的父节点是parent[x]

public:
    UF(int n) {
        this->count = n;
        parent.resize(n);
        for(int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }

    void Union(int p, int q) {
        int rootP = find(p);
        int rootQ = find(q);
        if(rootP == rootQ) return;
        parent[rootQ] = rootP;
        count--;
    }

    bool connected(int p, int q) {
        int rootP = find(p);
        int rootQ = find(q);
        return rootP == rootQ;
    }

    int find(int x) {
        // 根节点的parent[x] == x,层层向上找就好啦
        if(parent[x] != x) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }

    int getCount() { return count; }

};

int Kruskal(vector<vector<int>>& connections) {
    int n = connections.size();
//    序号从1 -> n
    UF uf(n + 1);
    sort(connections.begin(), connections.end(), [](auto& a, auto& b) { return a[2] < b[2]; });
    int mst = 0;
    for(auto c: connections) {
        int u = c[0], v = c[1], weight = c[2];
//        如果这两个结点是同一连通分量=> 则不能连接
        if(uf.connected(u, v)) continue;
        mst += weight;
        uf.Union(u, v);
    }
//    0开着没用
    return uf.getCount() == 2 ? mst : -1;
}

int main() {
    int n;
    cin >> n;
    vector<vector<int>> connections;
    while(n--) {
        int u, v, weight;
        cin >> u >> v >> weight;
        vector<int> temp(3);
        temp[0] = u, temp[1] = v, temp[2] = weight;
        connections.emplace_back(temp);
    }
    cout << Kruskal(connections);
    return 0;
}

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

class UF {
private:
    int count = 0;
    vector<int> parent;

public:
    UF(int n) {
        this->count = n;
        parent.resize(n);
        for(int i = 0; i < n; i++) parent[i] = i;
    }

    void Union(int p, int q) {
        int rootP = find(p), rootQ = find(q);
        if(rootP == rootQ) return;
        parent[rootQ] = rootP;
        count--;
    }

    bool connected(int p, int q) {
        int rootP = find(p), rootQ = find(q);
        return rootP == rootQ;
    }

    int find(int x) {
        if(parent[x] != x) parent[x] = find(parent[x]);
        return parent[x];
    }

    int getCount() { return count; }
};

class Solution {
public:
    int minCostConnectPoints(vector<vector<int>>& points) {
        // 这题要根据给的points先构造一个connections
        vector<vector<int>> connections;
        int n = points.size();
        for(int i = 0; i < n; i++) {
            for(int j = i + 1; j < n ; j++) {
                int xi = points[i][0], yi = points[i][1];
                int xj = points[j][0], yj = points[j][1];
                connections.push_back({i, j, abs(xi - xj) + abs(yi - yj)});
            }
        }
        // &不加是拷贝,会增加时间复杂度
        sort(connections.begin(), connections.end(), [](auto& a, auto& b){ return a[2] < b[2]; });
        int mst = 0;
        UF uf(n);
        for(auto& c: connections) {
            int u = c[0], v = c[1], weight = c[2];
            if(uf.connected(u, v)) continue;
            mst += weight;
            uf.Union(u, v);
        }
        return uf.getCount() == 1 ? mst : -1;
    }

};

http://www.niftyadmin.cn/n/253895.html

相关文章

Flutter 通过 VS code 连接 Android 模拟器(Windows)

环境配置 Flutterhttps://flutter.cn/docs/get-started/install/windowsAndroid Studiohttps://developer.android.google.cn/studioVS code安装Flutter插件https://flutter.cn/docs/get-started/editor?tabvscode夜神模拟器https://www.yeshen.com 注意事项 Flutter安装之…

设计模式 --- 行为型模式

一、概述 行为型模式用于描述程序在运行时复杂的流程控制&#xff0c;即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务&#xff0c;它涉及算法与对象间职责的分配。 行为型模式分为类行为模式和对象行为模式&#xff0c;前者采用继承机制来在类间分…

STM32的BOOT0和BOOT1配置

芯片启动时&#xff0c;SYSCLK的第4个上升沿&#xff0c;BOOT引脚的值将被锁存。用户设置BOOT0和BOOT1引脚状态&#xff0c;选择复位后的启动模式。 1、主闪存存储器 STM32内置Flash&#xff0c;用SWD/JTAG下载程序到这个Flash里&#xff0c;重启后直接从Flash里启动程序。 …

[python刷题模板] SortedList简易实现,支持单个添加/删除/查询名次

[python刷题模板] SortedList简易实现&#xff0c;支持单个添加/删除/查询名次 一、 算法&数据结构1. 描述2. 复杂度分析3. 常见应用4. 常用优化 二、 模板代码1. 模板 三、其他四、更多例题五、参考链接 一、 算法&数据结构 1. 描述 2. 复杂度分析 3. 常见应用 4.…

9.7 字符串的指针和指向字符串的指针变量

9.7 字符串的指针和指向字符串的指针变量 一.字符串表示形式二.字符串指针做函数参数1.数组名做函数参数2.数组指针做函数参数 三.字符指针变量与字符数组&#xff08;1&#xff09;字符数组是由若干个元素组成&#xff0c;每个元素中存放一个字符。&#xff08;2&#xff09;赋…

Vue CLI 插件和 Preset

插件 Vue CLI 使用了一套基于插件的架构。如果你查阅一个新创建项目的 package.json&#xff0c;就会发现依赖都是以 vue/cli-plugin- 开头的。插件可以修改 webpack 的内部配置&#xff0c;也可以向 vue-cli-service 注入命令。在项目创建的过程中&#xff0c;绝大部分列出的…

OS实战笔记(8)-- 设置基本OS基本工作环境

本笔记会搭建OS实战所需的虚拟机环境&#xff0c;主要是创建好虚拟机&#xff0c;设置虚拟机启动硬盘&#xff0c;在启动盘上安装Grub。 由于本专题是个人在业余时间除了Unity学习之外做的&#xff0c;没有时间和精力去解答具体的问题。本笔记中的实验个人在做的过程中除了遇到…

SpringBoot中使用redis事务

本文基于SpringBoot 2.X 事务在关系型数据库的开发中经常用到&#xff0c;其实非关系型数据库&#xff0c;比如redis也有对事务的支持&#xff0c;本文主要探讨在SpringBoot中如何使用redis事务。 事务的相关介绍可以参考&#xff1a; 0、起因 在一次线上事故中&#xff0c;我们…