当前位置: 首页 > news >正文

最小生成树——Kruskal

标题什么是生成树?

对于一张无向图,由nnn个顶点和n−1n-1n1条边构成地联通子图,叫做这个无向图 生成树

最小生成树就是指边权之和最小地生成树

请添加图片描述

如何求最小生成树?
Kruskal

介绍:

  1. 存图时只存每条边地起点、终点,而不关注节点之间地联通关系,所以不需要链式前向星邻接矩阵
  2. 然后使用边权排序,想像自己获得了nnn个点,现在需要给这nnn个点连边。
  3. 循环遍历存边地数组,对于每条边,取出它的两个端点:xxxyyy,同时使用并查集记录点与点之间是否联通。如果联通,则证明该点之间已经存在最优的边(因为权值更小的边已经排到前面去了,会被优先考虑)。如果不联通,就连上这两条边,使用并查集记录。
  4. 最后统计出该最小生成树的所有边的边权之和
代码实现

最小生成树模板题目

#include<bits/stdc++.h>
using namespace std;
int read(){int s=0,fl=1;char w=getchar();while(w>'9'||w<'0'){if(w=='-')fl=-1;w=getchar();}while(w<='9'&&w>='0'){s=s*10+(w^48);w=getchar();}return fl*s;
}
void out(int x){if(x<0)putchar('-'),x=-x;if(x<10)putchar(x+'0');else out(x/10),putchar(x%10+'0');
}
struct ed{int v,x,y;
}mp[1000010];
int f[1000010],cnt;
bool cmp(ed x,ed y){return x.v<y.v;
}
int find(int x){if(f[x]!=x) f[x]=find(f[x]);return f[x];
}
int n,m,ans;
int main(){n=read();m=read();for(int i=1;i<=m;i++){mp[i].x=read();mp[i].y=read();mp[i].v=read();//存边}sort(mp+1,mp+1+m,cmp);for(int i=1;i<=n;i++){f[i]=i;//初始化并查集}for(int i=1;i<=m;i++){int x=find(mp[i].x);int y=find(mp[i].y);if(x==y) continue;//如果最上层的祖先是一样的,则证明已经联通,跳过该条边f[x]=y;//将两条边的祖先连在一起cnt++;ans+=mp[i].v;//统计和}cnt==n-1?printf("%d",ans):printf("orz");//判断连上的节点数是否是整张图的节点数,如果不是就证明原图不连通,输出orzreturn 0;
}

双倍经验

P1967 [NOIP 2013 提高组] 货车运输

由题意可得AAA国由nnn个点,mmm条边构成,每条边权重为zzz,货车要从节点xxx走到节点yyy,每走一条边,货车的载重量不能超过当前边的权值。
此题在想不到最小生成树的情况下可以使用DijkstraDijkstraDijkstra,要求货车最大的载重量,肯定优先选择边权更大的边通过,于是设d[i]d[i]d[i]表示从节点xxx到节点iii的最大载重。判断逻辑显然可得:

if(new_dis>d[y]){d[y]=new_dis;

堆优化版DijkstraDijkstraDijkstra时间复杂度是O((V+E)logV) 但是这道题VVV=1e41e41e4,EEE=5e45e45e4,计算得最终为8.4e48.4e48.4e4,但是这只是单词DijkstraDijkstraDijkstra,算上询问次数,总时间约是2.4e92.4e92.4e9,一定超时
如果用离线处理,效率会高一些,但是还是无法通过此题

正解

使用最小生成树最近公共祖先(lca) 解决
因为无论如何货车走的路都一定是最大边权的边,然而生成树的性质有一条就是能联通所有节点,所以我们可以先对这张图求 最大生成树

然后对于每个询问xxxyyy,求出其最近公共祖先lll,然后在求lcalcalca途中维护w[i][j]w[i][j]w[i][j]表示从节点iii向上移动 2j 层后的最大值。

因为求lcalcalca的过程是倍增进行的,所以总时间复杂度是O(mlogm+nlogn+qlogn)O(m log m + n log n + q log n)O(mlogm+nlogn+qlogn)

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int read(){int s=0,fl=1;char w=getchar();while(w>'9'||w<'0'){if(w=='-')fl=-1;w=getchar();}while(w<='9'&&w>='0'){s=s*10+(w^48);w=getchar();}return fl*s;
}
void out(int x){if(x<0)putchar('-'),x=-x;if(x<10)putchar(x+'0');else out(x/10),putchar(x%10+'0');
}
int n,m,q;
int d[N],f[N],dep[N],fa[N][21];
int head[N],ne[N],to[N],v[N],tot,vis[N],w[N][21];
struct node{int x,y,v;
}mp[N];
bool cmp(node x,node y){return x.v>y.v;//求最大生成树
}
int find(int x){if(f[x]!=x) f[x]=find(f[x]);return f[x];
}
void add(int x,int y,int w){to[++tot]=y;ne[tot]=head[x];head[x]=tot;v[tot]=w;
}
void dfs(int x){vis[x]=1;for(int i=head[x];i;i=ne[i]){int u=to[i];if(vis[u]){continue;}dep[u]=dep[x]+1;fa[u][0]=x;w[u][0]=v[i];dfs(u);}
}
void kru(){for(int i=1;i<=n;i++){f[i]=i;}sort(mp+1,mp+1+m,cmp);for(int i=1;i<=m;i++){int x=find(mp[i].x);int y=find(mp[i].y);if(x==y){continue;}f[x]=y;add(mp[i].x,mp[i].y,mp[i].v);add(mp[i].y,mp[i].x,mp[i].v);}
}
int lca(int x,int y){if(find(x)!=find(y)){return -1;}int ans=2e9;if(dep[x]<dep[y]){swap(x,y);}for(int k=20;k>=0;k--){if(dep[fa[x][k]]>=dep[y]){ans=min(ans,w[x][k]);x=fa[x][k];}}if(x==y) return ans;for(int k=20;k>=0;k--){if(fa[x][k]!=fa[y][k]){x=fa[x][k];y=fa[y][k];}}ans=min(ans,min(w[x][0],w[y][0]));return ans;
}
int main(){n=read();m=read();for(int i=1;i<=m;i++){int x=read();int y=read();int v=read();mp[i].x=x;mp[i].y=y;mp[i].v=v;}q=read();kru();for(int i=1;i<=n;i++){if(vis[i]==1) continue;dep[i]=1;dfs(i);fa[i][0]=i;w[i][0]=2e9;}for(int i=1;i<=20;i++){for(int j=1;j<=n;j++){fa[j][i]=fa[fa[j][i-1]][i-1];w[j][i]=min(w[j][i-1],w[fa[j][i-1]][i-1]);//预处理倍增表}}for(int i=1;i<=q;i++){int x=read();int y=read();out(lca(x,y));putchar('\n');}return 0;
}
http://www.xdnf.cn/news/1389061.html

相关文章:

  • go 使用rabbitMQ
  • 【谷歌浏览器】浏览器实用自用版——谷歌浏览器(Google Chrome)离线纯净版安装 官方版无任何捆绑及广告 【离线安装谷歌浏览器】
  • 通过 KafkaMQ 接入Skywalking 数据最佳实践
  • R ggplot2学习Nature子刊一张图,换数据即可用!
  • leetcode 338 比特位计数
  • 04数据库约束实战:从入门到精通
  • Linux下的网络编程SQLITE3详解
  • 算法题打卡力扣第1004. 最大连续1的个数 III(mid)
  • 技术速递|新手指南:如何在 Foundry Local 中使用自定义模型
  • 百度后端岗位--面试真题分析
  • CCS的诡异报错合集1(以C2000为例)
  • MAC spotlight 搜不到应用程序和 tags 生效
  • ZooKeeper 安装配置
  • C++基础(②VS2022创建项目)
  • 球型摄像机实现360°无死角
  • CLion 中配置运行 Qt 项目指南
  • 三一重工AI预测性维护破局:非计划停机减少60%,技师转型与数字孪生技术搅动制造业
  • 预制菜餐厅:工业化与温度餐平衡术
  • 【Rust】 5. Trait 与运算符重载
  • Python Imaging Library (PIL) 全面指南:PIL高级图像处理-分割与颜色空间转换
  • [Mysql数据库] 知识点总结6
  • 人工智能-python-深度学习-批量标准化与模型保存加载详解
  • 嵌入式-定时器的从模式控制器、PWM参数测量实验-Day24
  • 快手发布SeamlessFlow框架:完全解耦Trainer与Agent,时空复用实现无空泡的工业级RL训练!
  • OpenTenBase实战:从MySQL迁移到分布式HTAP的那些坑与收获
  • MySQL數據庫開發教學(三) 子查詢、基礎SQL注入
  • java开发连接websocket接口
  • system论文阅读--HPCA25
  • 基于SpringBoot和百度人脸识别API开发的保安门禁系统
  • LubanCat-RK3568 UART串口通信,以及遇到bug笔记