并查集算法详解(C++)

  • 并查集基础
    • 并查集是什么?
    • 并查集的作用是什么?
    • 并查集的结构
      • 合并
      • 查询
    • 代码实现
      • 优化1:避免退化(按秩合并)
        • 代码优化
      • 优化2:路径压缩
        • 代码优化
    • 最终代码实现
    • 复杂度分析
    • 经典例题
      • 并查集入门
      • Wireless_Network
  • 并查集进阶1:带权并查集
    • 带权并查集是什么?
    • 带权并查集的作用是什么?
    • 经典例题
      • The_Suspects
  • 并查集进阶2:种类并查集
    • 种类并查集是什么?
    • 种类并查集的作用是什么?
    • 经典例题
      • 食物链
      • 关押罪犯

并查集基础

并查集是什么?

并查集是用来管理元素分组的算法。

并查集的作用是什么?

并查集可以高效的对元素进行分组(合并在一起),并且能快速的查询两个元素是否属于同一组。

并查集的结构

合并

并查集是一种树状结构。比如元素1和2属于同一组、元素1和3也属于同一组,那么元素2和3能通过元素1合并为同一组,即元素1为元素2和3的老大,那么元素1就是元素2和元素3在树状结构中的根。

当许多组元素需要合并在一起时,只需将各组元素的老大合并在一起即可,也就是让其中一个根指向另一个根,就使得两棵树合并成了一棵树,也就把两个组合并为了一个组。

查询

当我们要查询两个元素是否属于同一个组时,我们需要沿着各个节点往上向树的根进行查询,如果最终发现两个元素的根相同,那么他们就属于同一个组。反之,则不属于同一个组。


如图中:元素2和3的根都为元素1,故他们属于同一个组;元素2和7,他们的根分别为元素1和5,不同,故他们不属于同一个组。

代码实现

int f[maxn]; //全名为 father,父节点的意思//初始化 n个元素
void Init() {//使每个元素的根节点是其本身//即初始时每个元素都是单独的 for(int i=1; i<=n; i++) f[i]=i;
}
//查询树的根
//非递归实现
int Find(int i) {while(f[i] != i) {  //直到元素的父节点是它本身,表示已经查询到了树的根i = f[i];return i;          //返回根节点对应的元素
}//递归实现
int Find(int i) {if(f[i]==i)      //若元素的根节点为其本身,那么此元素就是树的根 return f[i];    //直接返回元素本身即可elsereturn Find(f[i]); //否则继续查询,知道查询到树的根位置
}//简化版
int Find(int i) {return f[i]==i ? f[i] : Find(f[i]);
}
//合并
void merge(int a, int b) {//先找到两个元素对应的根对应的元素 int fa = Find(a); int fb = Find(b);if(fa==fb) return;else f[fa]=fb;  //否则令元素 a的根指向元素 b的根
} //简化版
void merge(int a, int b) {f[Find(a)] = Find(b);
}

优化1:避免退化(按秩合并)

因为并查集的结构是树状结构,所以需注意退化问题。避免退化发生的方法如下:
首先,我们合并时,可记录这棵树的高度(记为rank)。接下来当我们需合并两棵树时,我们先对两棵树的高度进行判断,如不同,则让高度小的树的根指向高度大的根。如下图:

代码优化

对初始化(Init)函数和合并(merge)函数进行优化

//初始化优化
int f[maxn];
int h[maxn]; //全名为 heightvoid Init() {for(int i=1; i<=n; i++) {f[i] = i;h[i] = 0;  //令每棵树的高度初始值都为 0 }
}
//合并优化
void merge(int a, int b) {int fa = Find(a);int fb = Find(b);if(fa==fb) return; if(h[fa] < h[fb]) {  //如果元素 a对应的树的高度比 b小 f[fa] = fb;  //使元素 a的根指向元素 b的根 } else {f[fb] = fa;  //否则让元素 b的根指向元素 a的根 if(h[fa] == h[fb]) h[fa]++;// 如果两者对应的树的高度相同,则使新生成的树高度 +1 }
}

PTA L2-024 部落 (25 分)
在这题中,若不对merge进行优化就会运行超时

优化2:路径压缩

由于查询时我们需沿着元素所在的树从下往上查询,最终找到这棵树的根,表明这个元素与其根对应元素属于同一组。因为在此查询过程中我们会经过许多节点,而如果我们能将这个元素直接指向根节点,那么就能节省许多查询的时间。同时,在查询过程中,每次经过的节点,我们都可以同时将他们一起直接指向根节点。这样做的话,我们再查询这些节点时,就能很快知道他们的根是谁了。

代码优化

对查询(Find)函数进行优化

//查询优化
int Find(int i) {return f[i]==i ? f[i] : f[i] = Find(f[i]);//使元素直接指向树的根
}

最终代码实现

void Init() {for(int i=0; i<=n; i++) {f[i] = i;h[i] = 0;}
}
int Find(int i) {return f[i]==i ? f[i] : f[i]=Find(f[i]);
}
void merge(int a, int b) {int fa = Find(a);int fb = Find(b);if(fa != fb) {if(h[fa] < h[fb]) {f[fa] = fb;} else {f[fb] = fa;if(h[fa] == h[fb]) h[fa]++;}}
}

复杂度分析

经过两个优化后,并查集的效率变得非常高。对n个元素的并查集进行一次操作的均摊复杂度是O(a(n)) (a(n)是阿克曼函数的反函数),比优化前的O(log(n))还要快。

经典例题

并查集入门

Wireless_Network

并查集进阶1:带权并查集

带权并查集是什么?

带权是指一个元素具有额外的信息。比如元素1对应着数值6,元素2对应着数值4。这些带有信息的元素组成的并查集即为带权并查集。

带权并查集的作用是什么?

带权并查集能计算各个小组中元素的个数、能计算n个元素中还有几个元素没有加入小组中;计算分数、距离等等

注释:带权并查集需要在路径优化的基础下进行。

经典例题

The_Suspects

并查集进阶2:种类并查集

种类并查集是什么?

种类并查集是能把并查集分为几个部分,每个部分的种类不同。

种类并查集的作用是什么?

种类并查集能将两个阵容分开。比如把好人和坏人分为两个阵营。

经典例题

食物链

关押罪犯

参考资料:
《挑战程序设计竞赛》
路径压缩_并查集

并查集详解(C/C++)相关推荐

  1. 并查集详解 ——图文解说,简单易懂(转)特别好玩

    并查集详解 --图文解说,简单易懂(转) 2016年03月10日 17:38:08 阅读数:6931 标签: 并查集数据结构并查集算法图文解说 更多 个人分类: 算法--并查集 并查集是我暑假从高手那 ...

  2. - 并查集详解(第二节)

    以下是并查集思路详解: 一:概念 并查集处理的是"集合"之间的关系.当给出两个元素的一个无序数对(a,b)时,需要快速"合并"a和b分别所在的集合,这期间需要反 ...

  3. 并查集详解(从引入到代码)

    江湖上散落着各式各样的大侠,有上千个之多.他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的,就免不了要打一架.但大侠们有一个优点就是讲义气,绝对不打自己的朋友.而且他们信奉&qu ...

  4. 7-3 最小生成树-kruskal (10 分)(思路+详解+并查集详解+段错误超时解决)宝 Come

    一:前言 本题需要用到并查集的知识,建议先学完并查集后再看看本题 二:题目 题目给出一个无向连通图,要求求出其最小生成树的权值. 温馨提示:本题请使用kruskal最小生成树算法. 输入格式: 第一行 ...

  5. 拓扑排序 详解 + 并查集 详解 + 最小生成树详解

    若您发现本文有什么错误,请联系我,我会及时改正的,谢谢您的合作! 本文为原创文章,转载请注明出处 本文链接   : http://www.cnblogs.com/Yan-C/p/3943940.htm ...

  6. 一个很有意思的并查集详解

    并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了.以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定.不分享出来真是对不起party了.(party:我靠,关我嘛事啊?我跟你很熟么?) ...

  7. 深入浅出系列之——并查集详解【武侠版】【简单有趣】

    一个超级有意思,好懂的并查集解释 故事读完,并查集就会了 故事开始了...留神! 江湖上散落着各式各样的大侠,有上千个之多.他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的,就免 ...

  8. 并查集详解(一个有爱的江湖故事)

    大佬的并查集的江湖故事,一读就懂 例子就是杭电上的畅通工程: http://acm.hdu.edu.cn/showproblem.php?pid=1232 首先在地图上给你若干个城镇,这些城镇都可以看 ...

  9. 并查集详解,不会的同学可以来瞅瞅,转载的,不过加了一些自己的理解。

    并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了.以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定.不分享出来真是对不起party了.(party:我靠,关我嘛事啊?我跟你很熟么?) ...

  10. 数据结构(八):并查集详解 (多图+动图)

    目录 一.什么是并查集 二.并查集的存储结构 三.并查集的基本操作 (一)初始化 (二)Find操作 (三)Union操作 四.并查集的优化 (一)Union操作优化(小树并入大树) (二)Find操 ...

最新文章

  1. 【SVN】在阿里云上创建svn服务器
  2. 「镁客·请讲」仙知机器人赵越:“能友好工作”的机器人才能真正的为人类服务...
  3. zbb20171108 tomcat 性能优化
  4. 二分查找、变形及应用
  5. lua __index __newindex upvalue 示例
  6. 中国象棋程序的设计与实现(六)--N皇后问题的算法设计与实现(源码+注释+截图)...
  7. dbf 转mysql_DbfToMysql-DbfToMysql(Dbf数据转换Mysql工具)下载 v1.6官方版--pc6下载站
  8. spark大数据技术与应用 实训
  9. 3G模块拨号上网设置APN,拨号号码,帐号和密码
  10. 计算机加减乘除的公式,Word表格函数公式,轻松搞定加减乘除
  11. oracle- 同义词
  12. 【渝粤教育】国家开放大学2018年秋季 2745T农村经济管理 参考试题
  13. 常见问题 html5页面模板,html5+css3实现403程序报错页面模板特效
  14. Git之显示分支关系图(十五)
  15. python爬取知乎文章_Python爬取知乎日报,推送到kindle
  16. OBS 进阶之opengl使用方式 8 晶体管数字3 2 1倒计时显示
  17. 自然语言处理基于java实现(4) 之 基于VSM模型的信息检索程序
  18. 我国芯片的未来发展前景如何呢
  19. react-lazyload 源码解析
  20. 废旧Android手机搭建个人服务器:ksweb搭建Web服务器+Termux、Ngrok实现内网穿透

热门文章

  1. 【yum】yum 源的配置与使用
  2. keytool 使用
  3. python调节电脑音量_python如何调节音量大小
  4. 怎么把度分秒化成小数_度分秒转换成小数
  5. python读取lmdb文件_python中读写LMDB数据库
  6. 光纤传输与网络技术习题整理
  7. 使用微PE工具箱制作U盘启动盘
  8. c语言二级安卓软件,C语言二级考试题库安卓下载-C语言二级考试题库APK下载 - Iefans...
  9. VS2015+Qt5.13.1安装教程
  10. 如何做好一位合格qc_如何做好现场QC,一位老QC的经验分享