最小生成树(MST)详解+题目
原因
回顾一下旧知识
概况
在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得的 w(T) 最小,则此 T 为 G 的最小生成树。
\(\omega(t)=\sum\limits_{(u,v)\in t}{\omega (u,v)}\)
最小生成树其实是最小权重生成树的简称
思想
最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。
一、kruskal(克鲁斯卡尔)算法
1. 基本思想
基本思想是:假设连通网G = (V,E),令最小生成树的初始状态为只有 n 个顶点而无边的非连通图 T =( V , {} ),
图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边的顶点分别在T中不同的连通分量上,则将此边加入到T中
否则,舍去此边而选择下一条代价最小的边。依此类推,直至T中所有顶点构成一个连通分量为止
2. 时间复杂度
克鲁斯卡尔的时间复杂度主要由排序方法决定,而克鲁斯卡尔的排序方法只与网中边的条数有关,而与网中顶点的个数无关,
当使用时间复杂度为O(elog2e)的排序方法时,克鲁斯卡尔的时间复杂度即为O(log2e),
因此当网的顶点个数较多、而边的条数较少时,使用克鲁斯卡尔算法构造最小生成树效果较好
ps:记得配和并查集使用
二、prim(普里姆)算法
1. 算法介绍
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
3).重复下列操作,直到Vnew = V:
a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,
并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。
2. 时间复杂度
| 最小边、权的数据结构 | 时间复杂度(总计) |
|---|---|
| 邻接矩阵、搜索 | O(V^2) |
| 二叉堆、邻接表 | O((V + E) log(V)) = O(E log(V)) |
| 斐波那契堆、邻接表 | O(E + V log(V)) |
通过邻接矩阵图表示的简易实现中,找到所有最小权边共需O(V)的运行时间。
使用简单的二叉堆与邻接表来表示的话,普里姆算法的运行时间则可缩减为O(ElogV),其中E为连通图的边数,V为顶点数。
如果使用较为复杂的斐波那契堆,则可将运行时间进一步缩短为O(E+VlogV),
这在连通图足够密集时(当E满足Ω(VlogV)条件时),可较显著地提高运行速度。
(@百度百科)
题目
P3366 【模板】最小生成树
模板,致敬,我用的kruskal
#include <bits/stdc++.h>
using namespace std;
struct node{
int x,y,len;
}a[200005];
int f[100005];
int cmp(node num1,node num2){
return num1.len<num2.len;
}
int find(int x){
if (x!=f[x]) f[x]=find(f[x]);
return f[x];
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++){
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].len);
}
long long ans=0;
sort(a+1,a+1+m,cmp);
for (int i=1;i<=n;i++) f[i]=i;
for (int i=1;i<=m;i++){
int x=find(a[i].x),y=find(a[i].y);
if (x!=y){
ans+=a[i].len;
f[x]=y;
}
}
printf("%d",ans);
}
P1991 无线通讯网
** 其中主要就是kruskal,注意排序顺序和找第几大的边 **
#include <bits/stdc++.h>
using namespace std;
int n,m;
int x[1005],y[1005];
int f[1005];
struct node{
int l,r;
double len;
}a[250005];
int h=0;
double ans;
bool cmp(node num1,node num2){
return num1.len<num2.len;
}
int find (int x){
if (x!=f[x]) f[x]=find(f[x]);
return f[x];
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++){
scanf("%d%d",&x[i],&y[i]);
}
for (int i=1;i<=m;i++){
for (int j=i+1;j<=m;j++){
h++;
a[h].l=i;
a[h].r=j;
a[h].len=sqrt(pow(x[i]-x[j],2)+pow(y[i]-y[j],2));
}
}
sort(a+1,a+1+h,cmp);
for (int i=1;i<=m;i++){
f[i]=i;
}
int tot=0;
for (int i=1;i<=h;i++){
int x=find(a[i].l),y=find(a[i].r);
if (x!=y){
++tot;
ans=a[i].len;
f[x]=y;
}
if (tot==m-n){
printf("%.2lf",ans);
break;
}
}
return 0;
}
最小生成树(MST)详解+题目的更多相关文章
- 状压DP入门详解+题目推荐
在动态规划的题型中,一般叫什么DP就是怎么DP,状压DP也不例外 所谓状态压缩,一般是通过用01串表示状态,充分利用二进制数的特性,简化计算难度.举个例子,在棋盘上摆放棋子的题目中,我们可以用1表示当 ...
- 树形DP入门详解+题目推荐
树形DP.这是个什么东西?为什么叫这个名字?跟其他DP有什么区别? 相信很多初学者在刚刚接触一种新思想的时候都会有这种问题. 没错,树形DP准确的说是一种DP的思想,将DP建立在树状结构的基础上. 既 ...
- 最小生成树算法详解(prim+kruskal)
最小生成树概念: 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里 ...
- 数位DP入门详解+题目推荐
\(update:2019-9-6\) 博客里某些东西没有解释清楚,完善了对应的解释 在开始之前,我们先来看一道题--题目链接 题目要求,相邻两位的差大于等于2,那么我们先来构造一个试一试. 比如说\ ...
- 状压DP详解+题目
介绍 状压dp其实就是将状态压缩成2进制来保存 其特征就是看起来有点像搜索,每个格子的状态只有1或0 ,是另一类非常典型的动态规划 举个例子:有一个大小为n*n的农田,我们可以在任意处种田,现在来描述 ...
- 树形DP详解+题目
关于树形dp 我觉得他和线性dp差不多 总结 最近写了好多树形dp+树形结构的题目,这些题目变化多样能与多种算法结合,但还是有好多规律可以找的. 先说总的规律吧! 一般来说树形dp在设状态转移方程时都 ...
- DP+单调队列详解+题目
介绍: 单调队列优化的原理 先回顾单调队列的概念,它有以下特征: (1)单调队列的实现.用双端队列实现,队头和队尾都能插入和弹出.手写双端队列很简单. (2)单调队列的单调性.队列内的元素 ...
- Trie树(字典树,单词查找树)详解+题目
什么是字典树? 叫前缀树更容易理解 字典树的样子 Trie又被称为前缀树.字典树,所以当然是一棵树.上面这棵Trie树包含的字符串集合是{in, inn, int, tea, ten, to}.每个节 ...
- RHCE脚本题目详解
目录 RHCE脚本题目详解 题目一 shell脚本之if语句实现: shell脚本之case语句实现: 题目二 实现 测试 解析 写在后面 RHCE脚本题目详解 题目一 在system1上创建一个名为 ...
随机推荐
- HCNP Routing&Switching之BGP路由宣告
前文我们了解了BGP报文结构.类型以及邻居状态相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15422924.html:今天我们来聊一聊BGP路由宣告 ...
- Salesforce 生命周期管理(二)Agile & Scrum 浅谈
本篇参考: https://trailhead.salesforce.com/content/learn/modules/salesforce-agile-basics https://www.scr ...
- 【Java虚拟机10】ClassLoader.getSystemClassLoader()流程简析
前言 学习类加载必然离开不了sun.misc.Launcher这个类和Class.forName()这个方法. 分析ClassLoader.getSystemClassLoader()这个流程可以明白 ...
- vue3.x移动端页面基于vue-router的路由切换动画
移动端页面切换一般都具有动画,我们既然要做混合开发,做完之后还是不能看起来就像一个网页,所以我们基于vue-router扩展了一个页面切换push和pop的动画.这是一篇比较硬核的帖子,作者花了不少精 ...
- Codeforces1514B
问题描述 给你两个数n,k,问可以构造多少n个最大位数为k数按位与为0并且这n个数加起来最大的合法序列,答案对1e9 + 7取模. 思路分析 首先我们考虑这n个数按位与以后为0这个条件:我们可以知道, ...
- 为什么阿里巴巴开发手册中强制要求 POJO 类使用包装类型?NPE问题防范
封面:学校内的秋天 背景:写这个的原因,也是我这两天凑巧看到的,虽然我一直有 alibaba Java 开发手册,也看过不少次,但是一直没有注意过这个问题 属于那种看过,但又没完全看过 一起来看看吧冲 ...
- MyBatis源码分析(一):从JDBC到MyBatis 介绍MyBatis的背景,为什么要用MyBatis
一.介绍JDBC JDBC全称Java Database Connectivity,是Java语言规范客户端访问数据库的应用程序接口,所面向的数据库类型为关系型数据库. JDBC的三层架构图: JDB ...
- Envoy实现.NET架构的网关(三)代理GRPC
什么是GRPC gRPC是一种与语言无关的高性能远程过程调用 (RPC) 框架.gRPC 的主要好处是: 现代.高性能.轻量级的 RPC 框架. 契约优先的 API 开发,默认使用协议缓冲区,与语言无 ...
- 利用Ambari平台安装与部署Hadoop
* 本篇是利用Ambari平台安装与部署Hadoop,如果需要原生部署Hadoop,请点击以下地址: https://www.cnblogs.com/live41/p/15467263.html 一. ...
- 转:VCS仿真vivado IP的方法
vivado中的仿真库和模型与ISE中的是不一样的,因此在vivado中使用VCS进行仿真的方法也与ISE中不一样. VCS可以通过两种方法对XILINX的器件进行功能仿真和门级仿真,这两种方法是 P ...