算法模板:模拟数据结构之并查集

简介: 算法模板:模拟数据结构之并查集


并查集


并查集作用:

1.将两个集合合并

2.询问两个元素是否在一个集合当中


基本原理:


每个集合用一颗树来表示。树根的编号就是整个集合的编号。每个节点都存的是它的父节点,即 p [x] 表示 x 的父节点。


p[x]中储存的是每个节点的父节点,一开始并不是树状的,


而是一个个单独的节点,每个节点都是根节点,都有集合编号,然后通过不断的合并才形成的树状结构


问题一: 如何判断树根


if (p[x]==x)


除根节点以为所有节点都存的是自身的父节点,只有根节点存的是它自己。


问题二: 如何求x的集合编号


没找到就一直访问到它的父节点,直到找到位置。


while (p[x] != x) x = p[x]


优化:路径压缩

只要某一个元素找的根节点

就把这个元素的所有祖宗节点都改成根节点。


int find(int x)
{
  if(p[x]!=x)// x不是自身的父亲,即x不是该集合的代表
    return p[x]=find(p[x]);
    return p[x]; // 查找x的祖先直到找到代表,于是顺手路径压缩
}


问题三:如何合并两个集合


     p [find(a)] = p[find(b)];


p[x]=x的集合编号,p[y]是y的集合编号


代码实现


#include<bits/stdc++.h>
using namespace std;q
const int N = 1e6+10;
int p[N];
int find(int x)
{
  if(p[x]!=x)// x不是自身的父亲,即x不是该集合的代表
    return p[x]=find(p[x]);
    return p[x]; // 查找x的祖先直到找到代表,于是顺手路径压缩
}
int main()
{
  int n,m;
  cin>>n>>m;  
  for(int i = 1 ; i <= n ; i ++)  p[i]=i;
    //开始时每个节点都是父节点
  while(m--)
  {
    string x; cin>>x;
    int a,b; cin>>a>>b;
    if(x=="M")
    p[find(a)]=find(b);//a集合的根节点的父节点变成 b集合的根节点 完成a集合与b集合的合并
    else
    {
      if(find(a)==find(b))
      cout<<"Yes";
      else
      cout<<"No";
      puts("");
    }
  }
  return 0;
}


村村通

某市调查城镇交通状况,得到现有城镇道路统计表。表中列出了每条道路直接连通的城镇。市政府 “村村通工程” 的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要相互之间可达即可)。请你计算出最少还需要建设多少条道路?


输入格式


输入包含若干组测试测试数据,每组测试数据的第一行给出两个用空格隔开的正整数,分别是城镇数目 nnn 和道路数目 mmm ;随后的 mmm 行对应 mmm 条道路,每行给出一对用空格隔开的正整数,分别是该条道路直接相连的两个城镇的编号。简单起见,城镇从 111 到 nnn 编号。


注意:两个城市间可以有多条道路相通。


输出格式


对于每组数据,对应一行一个整数。表示最少还需要建设的道路数目。


输入 #1


4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0


输出 #1


1
0
2
998


思路:


先初始化,将自己父亲等于自己


**输入两个村庄后就把它们连起来,输入完毕后遍历 从 1 到 n,判断 节点是不是等于他们的父节点 **


所以如果i的父亲为它本身的话 说明 编号为 i 的这条路,与其他路不连通,ans++


但还有一种情况是会有一个节点是所有其他节点的祖先节点,也而且祖先节点也等于他本身、


所以最后需要 ans - 1


#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int p[N];
int find(int x)
{
  return (p[x]!=x)?p[x]=find(p[x]):p[x];
}
int main()
{
  int n,m;
  while(cin>>n>>m)
  {
    int a,b;
    int ans=0;
    for(int i = 1 ; i <= n ; i ++)
    p[i]=i;
    while(m--)
    {
      cin>>a>>b; 
      a=find(a),b=find(b);
      p[a]=p[b];
    }
    for(int i = 1 ; i <= n; i ++)
    {
      if(find(i)==i)
      ans++;
      //如果自己等于自己的父亲 就说明 编号为 i 的这条路,与其他路不连通 
    }
    cout<<ans-1<<"\n";
        //要减一是因为如果不用修一条路的话 那就会有一个节点是所有其他节点的祖先节点 所以要减去1 
  }
  return 0; 
 } 


完结散花

ok以上就是对 模拟数据结构之并查集 的全部讲解啦,很感谢你能看到这儿。如果有遗漏、错误或者有更加通俗易懂的讲解,欢迎小伙伴私信我,我后期再补充完善。

相关文章
|
2月前
|
存储 监控 算法
基于 Go 语言跳表结构的局域网控制桌面软件进程管理算法研究
针对企业局域网控制桌面软件对海量进程实时监控的需求,本文提出基于跳表的高效管理方案。通过多级索引实现O(log n)的查询、插入与删除性能,结合Go语言实现并发安全的跳表结构,显著提升进程状态处理效率,适用于千级进程的毫秒级响应场景。
169 15
|
2月前
|
分布式计算 并行计算 算法
《数据之美》:图结构的精妙世界与算法实践
图是表示多对多关系的非线性数据结构,由顶点和边组成,可建模社交网络、路径导航等复杂系统。核心算法包括BFS/DFS遍历、Dijkstra最短路径、Floyd-Warshall全源最短路径,以及Prim和Kruskal最小生成树算法,广泛应用于推荐系统、社交分析与路径规划。
|
3月前
|
运维 监控 JavaScript
基于 Node.js 图结构的局域网设备拓扑分析算法在局域网内监控软件中的应用研究
本文探讨图结构在局域网监控系统中的应用,通过Node.js实现设备拓扑建模、路径分析与故障定位,提升网络可视化、可追溯性与运维效率,结合模拟实验验证其高效性与准确性。
265 3
|
3月前
|
存储 监控 算法
企业电脑监控系统中基于 Go 语言的跳表结构设备数据索引算法研究
本文介绍基于Go语言的跳表算法在企业电脑监控系统中的应用,通过多层索引结构将数据查询、插入、删除操作优化至O(log n),显著提升海量设备数据管理效率,解决传统链表查询延迟问题,实现高效设备状态定位与异常筛选。
142 3
|
算法 开发者 计算机视觉
燃爆全场!Python并查集:数据结构界的网红,让你的代码炫酷无比!
在编程的世界里,总有一些数据结构以其独特的魅力和高效的性能脱颖而出,成为众多开发者追捧的“网红”。今天,我们要介绍的这位明星,就是Python中的并查集(Union-Find)——它不仅在解决特定问题上大放异彩,更以其优雅的设计和强大的功能,让你的代码炫酷无比,燃爆全场!
169 0
|
9月前
|
算法 安全 搜索推荐
套用算法模板备案审核问题增多的原因及解决建议
随着算法备案要求的完善,企业常因使用网上廉价模板而遭遇审核通过率低、问题增多的困境。本文分析了审核不通过的原因,包括模板缺乏针对性、审核标准严格、审核人员主观差异及企业准备不足等,并提出建议:深入了解备案要求、准备详尽材料、避免通用模板、寻求专业帮助。备案后还需持续合规管理,确保算法服务安全运行。
|
算法
【算法】前缀和——二维前缀和模板题
【算法】前缀和——二维前缀和模板题
168 0
|
10月前
|
存储 算法 iOS开发
【狂热算法篇】并查集:探秘图论中的 “连通神器”,解锁动态连通性的神秘力量(通俗易懂版)
【狂热算法篇】并查集:探秘图论中的 “连通神器”,解锁动态连通性的神秘力量(通俗易懂版)
|
算法 JavaScript 前端开发
第一个算法项目 | JS实现并查集迷宫算法Demo学习
本文是关于使用JavaScript实现并查集迷宫算法的中国象棋demo的学习记录,包括项目运行方法、知识点梳理、代码赏析以及相关CSS样式表文件的介绍。
138 7
第一个算法项目 | JS实现并查集迷宫算法Demo学习
|
存储 缓存 算法
通过优化算法和代码结构来提升易语言程序的执行效率
通过优化算法和代码结构来提升易语言程序的执行效率
319 2

热门文章

最新文章