当前位置: 首页 > 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.jsqmd.com/news/67499/

相关文章:

  • 大模型应用开发LangChain框架 - yi
  • 侯捷 C++ 系列课程
  • 割点
  • 2025年渔具实测:新款鲫鱼竿超轻硬,高性价比钓鱼竿真靠谱
  • 2025年国产鱼竿十大品牌:优选前十的口碑鱼竿盘点
  • 2025.12.01~2025.12.07
  • MySQL怎么保证高可用
  • 2025钓鱼竿品牌前十名,口碑好的牌子都在这:耐用款合集
  • ## AI浪潮下的冷思考:技术、泡沫与我们的未来
  • CVE-2025-10971:敏感信息不安全存储漏洞深度解析
  • Flink学习笔记:时间与Watermark
  • 第11章 泛型、trait与生命周期 - 实践
  • Steger 脊线提取算法原理
  • omniinfer vllm v0.9.0整体框架图和pangu7b模型图
  • 异动拉升横盘突破筛选股票
  • ARC 078D
  • 过碳酸钠源头工厂在哪里?过碳酸钠直销厂家:含氧量高的过碳酸钠厂家推荐
  • 过碳酸钠生产厂家盘点:靠谱过碳酸钠厂家、优质供应商、制造商汇总
  • 国内生产过碳酸钠的厂家有哪些?质量好的过碳酸钠厂家盘点
  • CTT 2026 游记
  • 基于奇异值分解的点云配准原理
  • 成膜助剂供应商推荐:实力厂家/批发商货源稳定有保障
  • LogFilter Panel: 我做了一个 grafana 中更好用的 VictoriaLogs 日志筛选面板
  • 像Git一样管理数据:深入解析数据库并发控制MVCC的实现
  • 13.结构型 - 适配器模式 (Adapter Pattern)
  • 决策单调性(四边形不等式)学习笔记
  • Classic Papers in Programming Languages and Logic | 阅读计划
  • CodeBuddy AI IDE:全栈AI创建平台实战
  • 廊坊婚介所见证:放下挑剔的女人,幸福来得很快
  • Tauri 窗口拖拽功能偶尔失效问题修复总结