Kruskal最小生成树【详细解释+动图图解】【sort中的cmp函数】 【例题:洛谷P3366 【模板】最小生成树】

本文主要是介绍Kruskal最小生成树【详细解释+动图图解】【sort中的cmp函数】 【例题:洛谷P3366 【模板】最小生成树】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • Kruskal算法简介
    • Kruskal算法前置知识
      • sort 中的cmp函数
  • 算法思考
    • 样例详细示范与解释
    • kruskal模版code↓
  • 例题:洛谷P3366 【模板】最小生成树code↓
  • 完结撒花QWQ

Kruskal算法简介

K r u s k a l Kruskal Kruskal 是基于贪心算法 M S T MST MST 算法,核心思想为以边为中心查找最小生成树,时间复杂度 O ( m l o g 2 m ) O(mlog_{2}m) O(mlog2m),其中的 m m m 为边数

具体算法可分为两个步骤

1.以边权为优先级来进行排序

2.使用并查集查找连通性,如果不连通,则加边,加答案


Kruskal算法前置知识

1.对于 v e c t o r vector vector 的容器排序算法(使用 s o r t sort sort 即可)

sort(T.begin(),T.end(),cmp);//这是vector的排序方法

解释: T . b e g i n ( ) T.begin() T.begin() v e c t o r vector vector 的起始部分, T . e n d ( ) T.end() T.end() v e c t o r vector vector 的结束部分, T T T v e c t o r vector vector 的容器名

sort 中的cmp函数

c m p cmp cmp s o r t sort sort 重构函数,需要自己定义,这个函数的类型 b o o l bool bool内部变量的类型便是需要排序的容器的类型

cmp模版code如下↓

T name;
bool cmp(T x,T y){return x op y}
sort(name(first),name(last),cmp)

T T T容器类型 n a m e name name容器名字 n a m e ( f i r s t ) name(first) name(first) 代表容器的第一位 n a m e ( l a s t ) name(last) name(last) 表示容器的最后一位


2.使用结构体的构造来赋值

Edge(int a,int b,int c):u(a),v(b),w(c){};

上述构造函数的代码的意思等同于↓:

Edge(int a,int b,int c){u=a,v=b,w=c;}

在结构体里加边的操作也就为:T.push_back(Edge(u,v,w));


3.容器 v e c t o r vector vector 的定义

我们需要用容器来管理结构体

也就是将结构体给定义在容器里

vector<Node> T;//其中T为容器名,Node为结构体名

定义code总结↓:

struct Node{int u,v,w;//定义类型Edge(int a,int b,int c):u(a),v(b),w(c){};//使用构造
};
bool (Node x,Node y){return x.w<y.w}//具体使用vector里的哪一个定义排序的函数
vector<Node> T;//使用容器来管理结构体
sort(T.begin(),T.end(),cmp)//其中T为容器名

算法思考

我们先给出一个题目来进行思考↓:

x x x 市共有 n n n 个岛屿, m m m 种修桥的方案由于 x x x 市的市长是一个黑心市长,所以他想要选择一种方案使得总共修桥的钱最少
每年他可以修一座桥,问:需要几年才能使得所有的岛屿之间都可以互相同行,最少修桥的钱为多少?

我们可以知道:修桥的钱数就是边权,岛屿的名字就是点的编号

第一个问题很好解答,使得所有点之间都可以连通的最少边数 N − 1 N-1 N1 条边

第二个问题我们就需要进行 K r u s k a l Kruskal Kruskal 进行求最小生成树

输入格式为
1 1 1 行,两个整数 n n n , m m m
2 2 2 ~ n + 1 n+1 n+1 行,每行三个整数 u u u , v v v , w w w ,表示所连接的两点及其边权

我们先给出一组样例↓

4 6
1 2 11
2 3 13
3 4 9
4 1 21
1 3 23
4 2 20

样例解释如图示↓
在这里插入图片描述

样例详细示范与解释

因为我们是需要" 花最少的钱,办最多的事 ",所以我们需要先以边的权值为优先级进行排序,结果为↓

3 4 9
1 2 11
2 3 13
4 2 20
4 1 21
1 3 23

那么我们就可以开始进行判断了,每一次重复的过程为:查找两个点是否连通,如果不连通,则加边

int x=find(wei[i].u),y=find(wei[i].v);//查找两个点的祖先if(x!=y){//如果祖先相同,则他们连通,在同一个集合内f[x]=y;//将两条边连在一起ans+=wei[i].w;//将它的权值加在最终答案里cnt++;//已经连接的边数+1}

解释:因为我们最开始已经排过序了,所以如果不连通,那么这条边一定是连接这两个点的最小代价

最后,如果两个点不连通,直接加边和答案,如果边数已经满足最少边数 N − 1 N-1 N1 条,则返回答案

return cnt==n-1?ans:-1;//如果边数是n-1条则返回答案,否则没有答案,无法连接所有边

如何使用并查集查找两个点的连通性,可见我的另一篇博文:并查集【模版】& 路径压缩优化

动图视频如下:

kruskal模版code↓

int kruskal(int n,int m,vector<Edge> &wei){sort(wei.begin(),wei.end(),cmp);int ans=0,cnt=0;for(int i=0;i<m;i++){int x=find(wei[i].u),y=find(wei[i].v);if(x!=y){f[x]=y;ans+=wei[i].w;cnt++;}}return cnt==n-1?ans:-1;
}

例题:洛谷P3366 【模板】最小生成树code↓

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+7;
struct Edge{int u,v,w;Edge(int a,int b,int c):u(a),v(b),w(c){};
};
int f[maxn]={},n,m;
bool cmp(Edge x,Edge y){return x.w<y.w;
}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);} 
vector<Edge> wei;
int kruskal(int n,int m,vector<Edge> &wei){sort(wei.begin(),wei.end(),cmp);int ans=0,cnt=0;for(int i=0;i<m;i++){int x=find(wei[i].u),y=find(wei[i].v);if(x!=y){f[x]=y;ans+=wei[i].w;cnt++;}}return cnt==n-1?ans:-1;
}
int init(){for(int i=1;i<=n;i++) f[i]=i;return 0;
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++) f[i]=i;for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;wei.push_back(Edge(u,v,w));//因为是无向图,所以需要反过来再加一次边wei.push_back(Edge(v,u,w));}int ans=kruskal(n,2*m,wei);//因为是无向图,所以边数是原边数的两倍if(ans==-1) cout<<"orz";else cout<<ans;return 0;
}

这么一点代码当然是可以 A C AC AC

在这里插入图片描述

完结撒花QWQ

这篇关于Kruskal最小生成树【详细解释+动图图解】【sort中的cmp函数】 【例题:洛谷P3366 【模板】最小生成树】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/844723

相关文章

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3

java中使用POI生成Excel并导出过程

《java中使用POI生成Excel并导出过程》:本文主要介绍java中使用POI生成Excel并导出过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求说明及实现方式需求完成通用代码版本1版本2结果展示type参数为atype参数为b总结注:本文章中代码均为

在java中如何将inputStream对象转换为File对象(不生成本地文件)

《在java中如何将inputStream对象转换为File对象(不生成本地文件)》:本文主要介绍在java中如何将inputStream对象转换为File对象(不生成本地文件),具有很好的参考价... 目录需求说明问题解决总结需求说明在后端中通过POI生成Excel文件流,将输出流(outputStre

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

通过Docker Compose部署MySQL的详细教程

《通过DockerCompose部署MySQL的详细教程》DockerCompose作为Docker官方的容器编排工具,为MySQL数据库部署带来了显著优势,下面小编就来为大家详细介绍一... 目录一、docker Compose 部署 mysql 的优势二、环境准备与基础配置2.1 项目目录结构2.2 基

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

kotlin的函数forEach示例详解

《kotlin的函数forEach示例详解》在Kotlin中,forEach是一个高阶函数,用于遍历集合中的每个元素并对其执行指定的操作,它的核心特点是简洁、函数式,适用于需要遍历集合且无需返回值的场... 目录一、基本用法1️⃣ 遍历集合2️⃣ 遍历数组3️⃣ 遍历 Map二、与 for 循环的区别三、高

Linux系统中配置静态IP地址的详细步骤

《Linux系统中配置静态IP地址的详细步骤》本文详细介绍了在Linux系统中配置静态IP地址的五个步骤,包括打开终端、编辑网络配置文件、配置IP地址、保存并重启网络服务,这对于系统管理员和新手都极具... 目录步骤一:打开终端步骤二:编辑网络配置文件步骤三:配置静态IP地址步骤四:保存并关闭文件步骤五:重

Centos环境下Tomcat虚拟主机配置详细教程

《Centos环境下Tomcat虚拟主机配置详细教程》这篇文章主要讲的是在CentOS系统上,如何一步步配置Tomcat的虚拟主机,内容很简单,从目录准备到配置文件修改,再到重启和测试,手把手带你搞定... 目录1. 准备虚拟主机的目录和内容创建目录添加测试文件2. 修改 Tomcat 的 server.X