用并查集识别隧道相邻测线的共有病害
业务场景
隧道里有多条平行的测线,相邻两条(编号差 1)上要是各有一个病害、里程范围还重叠,那很可能就是同一个病害在两条测线上各露了一面——这种得标成”共有病害”。
难点在传递性
判断这事不能光看两两配对,因为重叠是会传递的:A 和 B 重叠、B 又和 C 重叠,那 A、B、C 其实是同一组,该归到一块儿。要是只两两标记,A-B 一组、B-C 一组,C 跟 A 之间的关系就丢了,分出来的组是碎的。
并查集(Union-Find)
这种”沾边就连、要整体分组”的活,正好是并查集擅长的:
class UnionFind(n: Int) { |
流程大概是:
- 先把所有”相邻测线、里程重叠”的病害对找出来。
- 每一对调一次
union(a, b)。 - 最后
find(x)结果相同的,就是同一组。
里面用了路径压缩和按秩合并两个优化,每次 find/union 基本接近 O(1),几千个病害也就是眨眼的事。
后面再碰到类似的活——社交网络分簇、等价类合并、连通分量——都可以照这个套路上并查集,比写图遍历或者两两聚类都省事。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 CYK's Blog!
评论
