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

20251206 - 并查集 总结

并查集介绍

正常情况下我们维护一棵树,存储了每条边、每个点的具体信息,因为我们需要知道一棵树的完整面貌。

但是如果我们只想知道这棵树,或者说这个森林的连通情况,就完全没必要这么麻烦了。

假设我们只存储每个节点的父亲节点 \(fa_u\),那么该如何判断 \(u\)\(v\) 是否处在同一棵树中呢?很简单,只需要沿着 \(u\)\(v\) 的父亲 \(fa\) 不断往上爬找到根,判断根是否相等即可。

合并 \(u\)\(v\) 的时候,找到它们分别的根 \(fu\)\(fv\),让 \(fa_{fv} = fu\) 即可。

这就是并查集。

朴素实现

需要一个 Find_Father 函数去找节点对应的根节点,这边为了简写就简称 FF 函数了。以及需要一个 Merge 函数用作合并。

朴素实现的代码如下:

int FF(int u){if(fa[u]==u)return u;return FF(fa[u]);
}
void Merge(int u,int v){int fu=FF(u),fv=FF(v);if(fu!=fv)fa[fv]=fu;return;
}

时间复杂度是多少呢?发现当最坏情况下,树呈链状,一次 FF 可能就需要 \(O(n)\) 的时间。如果需要连 \(m\) 条边,时间复杂度 \(O(nm)\),太差了。这就完全失去并查集的意义了,跑 BFS 都比这快。

优化

刚才我们发现并查集的朴素实现,时间复杂度极差。需要对它进行优化。

一般有以下两种优化方案:

  • 路径压缩

    • 由于在并查集中,我们只关心连通情况,其实并不关心你具体的父节点究竟是谁,也就是不关心树的具体形态。
    • 那么我们完全可以考虑在查询根节点的同时,把路径上的节点的父节点修改成根节点。
    • 这样就可以大大加快后续的查询速度,均摊每次操作时间复杂度 \(O(\log n)\)
    • 代码实现:
      int FF(int u){if(fa[u]==u)return u;return fa[u]=FF(fa[u]);
      }
      /*
      可以使用三目运算符压行
      int FF(int u){return (fa[u]=u?u:fa[u]=FF(fa[u]));}
      */
      
    • 一般的题目只需要用到这个优化就可以过得去了。
  • 启发式合并

    • 在合并时,我们考虑把节点数量较少的树的根节点合并到节点数量较多的树的根节点下面。
    • 也可以根据树的深度来合并。
    • 这样就能使新树的每个节点到根节点的总距离尽可能小。
    • 这个优化会大大提升速度,均摊一次操作 \(O(\alpha(n))\),其中 \(\alpha(n)\) 可以看做一个不超过 \(4\) 的小常数,几乎可以忽略不计。
    • 代码实现:
      void Merge(int u,int v){int fu=FF(u),fv=FF(v);if(fu==fv)return;if(sz[fv]>sz[fu])swap(fu,fv);fa[fv]=fu,sz[fu]+=sz[fv];return;
      }
      
    • 启发式合并是一个很通用的优化方法,它的作用不仅在于并查集。

例题选讲

这次是真的选讲了喵!题太多太多了喵!

D - 朋友

在一对朋友之间连边,用两个并查集维护出两个公司分别的连通情况,多维护一个 \(sz\)。对小明和小红分别所处的集合里的人数取 \(\min\) 就是答案。

E - 营救

乍一看这个题跟并查集毫无关系,因为它是要你算什么最小的拥挤度最大值。但是,最大值最小,你没有想到二分吗?答对了就是二分!我们二分这个最大的拥挤度,然后去 check

check 怎么写?由于现在已经固定了最大的拥挤度,于是只需要判断能不能从 \(s\)\(t\) 去就可以了,考虑连边。但是由于拥挤度有最大值上限,因此拥挤度超过最大值上限的边就不能够被加入并查集中去进行维护。

由于需要搞多次并查集,一定要记得初始化喔。

http://www.zskr.cn/news/78028.html

相关文章:

  • 侯捷 C++ 系列课程
  • Flink学习笔记:时间与Watermark
  • 第11章 泛型、trait与生命周期 - 实践
  • ARC 078D
  • CTT 2026 游记
  • 基于奇异值分解的点云配准原理
  • LogFilter Panel: 我做了一个 grafana 中更好用的 VictoriaLogs 日志筛选面板
  • 13.结构型 - 适配器模式 (Adapter Pattern)
  • Tauri 窗口拖拽功能偶尔失效问题修复总结
  • PyTorch推理扩展实战:用Ray Data轻松实现多机多卡并行
  • 2025婴儿车性价比排行榜首选:UPPAbaby MINU V3如何以轻便全能理念重新定义价值标准(附权威认证)
  • Java数组
  • 洛谷 P8189
  • 12月8日
  • 你在用什么免费ip库?
  • 香橙派上进行 Livox Mid-360 激光雷达开发(二)移植FAST_LIO
  • 10406_基于Springboot的社交平台系统
  • 2025 年 12 月杭州公寓出租权威推荐榜:精选浙江优质房源,温馨宜居与便捷交通的完美之选
  • 2025云南短视频制作服务商/公司TOP5推荐!昆明等地短视频制作企业榜单发布,赋能企业品牌传播新生态
  • 极速AI助手 - 多AI服务桌面助手, 支持MCP工具调用, 内置免费AI功能
  • Python函数基础实战教程:从定义调用到参数传值全解析
  • 获取数组长度即最大下标
  • 白带异常用药推荐:科学应对妇科炎症的健康指南
  • 第49天
  • 洛谷 P3959
  • 东城区离婚律师事务所推荐:专注婚姻家事的法律服务机构
  • 水下的成长——Goodbye 2025
  • 口碑好的治疗白带异常的品牌推荐 女性健康守护指南
  • Codeforces Round 1069 (Div. 2) A-E2
  • 北京胜率高的婚姻律师事务所有哪些