图论-最小生成树<Kruskal>
以上是昨天的Blog,有需要者请先阅读完以上再阅读今天的Blog。
可能今天的有点乱,好好理理,认真看完相信你会懂得
然而,文中提到的所有的算法在本人Blog中都会后期有讲解。推荐Blog
分割线
第三天
引子:昨天我们简单讲了讲最小生成树<Dijkstra,Floyd>算法,今天的课程就开始啦!
今天我们要讲的是:最小生成树
Top1:最小生成树的概念
最小生成树,听起来好像是树呀,为什么会是图论呢?其实,处理最小生成树问题前给出的东西,就是一个图,只不过进行操作后要求变成一个最小生成树罢了。
那什么是最小生成树呢?
我们把这个词语拆开来看。
树 ,我们都好理解,父亲儿砸祖先啥的如果不知道的话......先百度完树再来看吧 ,那么我们根据树的特性可以得出一个结论:
最小生成树是没有环的
生成树 ,就是一个点到另一个点的路径是 唯一的 ,(可以通过树的无环性质证明),也就是 一个用N-1条边连接的树,且所有点到其他点的路径唯一
最小 代表最终生成树的边权和最小(不知道什么是边权的到博主的Blog里面去看吧)。
这里就有一个问题了:为什么会是N-1条边呢,而不是N-2或者N+1条边?
既然要把N个点用最少数量的边(这里不是上面“最小”的定义)将所有点连接起来,(忽略边权)上过小学的都知道,将两个点连起来是要一条边,三个点要两条边,哪里见过三个点用一条边连起来的?用N条边或N+1条边(即上述例子的三条边或四条边),自然就会浪费边了。
### 主要还是靠自己动手画图思考。
Top2:算法-Kruskal
概念我们讲完了,进入正题。
其实最小生成树还有个算法叫做Prim,Prim算法和Kruskal算法在于,一个在稀疏图中更快,一个在稠密图中更快。然而,Kruskal在比赛中会更好用。
那讲了这么多,Kruskal到底怎么用呢?
我们都知道了数没有环,那么只需要每次取权值最小的边,只要加入这条边之后不行成环,就可以。
有点像贪心,但是要判断有没有环。
怎么判断有环没环呢?
——并查集
所以代码就很简答啦!
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 5000 + 10;
struct Line{
int x, y;
int dis;
bool operator < (const Line& next) const {
return dis > next.dis;
}
};
priority_queue<Line> line;
int n, m, now;
int fa[MAXN];
int ans;
inline int read(){
int f = 1, x = 0;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
c = getchar();
}
return f * x;
}
int find(int x){
if(fa[x] == x)return x;
return fa[x] = find(fa[x]);
}
int main(){
n = read(),m = read();
for(int i = 1;i <= m; i++){
int x,y,z;
x = read(),y = read(),z = read();
Line tot = {x,y,z};
line.push(tot);
}
for(int i = 1;i <= n; i++){
fa[i] = i;
}
while(!line.empty()){
Line tot = line.top();
line.pop();
int nx = tot.x, ny = tot.y;
if(find(nx) == find(ny)){
continue;
}
fa[find(nx)] = find(ny);
ans += tot.dis;
now++;
if(now == n - 1){
printf("%d",ans);
return 0;
}
}
puts("orz");
return 0;
}
原文地址:https://www.cnblogs.com/CJYBlog/p/MST.html
- 针对近期“博全球眼球的OAuth漏洞”的分析与防范建议
- 黑掉美国(英国、澳大利亚、法国等)的交通控制系统
- Android 自定义标签 ViewLayout
- Identity Service - 解析微软微服务架构eShopOnContainers(二)
- 机器学习之随机森林
- Catalog Service - 解析微软微服务架构eShopOnContainers(三)
- EventBus In eShop -- 解析微软微服务架构Demo(四)
- Health Check in eShop -- 解析微软微服务架构Demo(五)
- Android Studio相见恨晚的操作锦集
- [收藏]几个常用的用正则表达式验证字符串的函数
- 走进科学: 无线安全需要了解的芯片选型、扫描器使用知识
- React Native之携程Moles框架
- 从Android短信漏洞到手机钓鱼木马
- 老外手把手带你搭建DMZ渗透测试实验室(Part 1,2)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- fgsea做GSEA
- 27.opengl高级光照-点光源阴影
- 28.opengl高级光照-法线贴图
- python抓取动态验证码,具体第几帧数的位置静态图片
- 在 Spring Security 中,我就想从子线程获取用户登录信息,怎么办?
- php自动加载
- 011.Nginx防盗链
- 012.Nginx负载均衡
- 013.Nginx动静分离
- 014.Nginx跨域配置
- 深入理解 FilterChainProxy【源码篇】
- matplotlib基础绘图命令之bar
- 使用 Github Actions 自动部署 Angular 应用到 Github Pages
- 路径中关于斜杠/和反斜杠 的区别
- Redis的高级特性与应用场景(二)