483 字
2 分钟
代码随想录算法训练营第四十七天 | 图论 Part05
并查集理论
-
并查集(Union-Find) 是一种用于处理不交集(Disjoint Set)的数据结构,常用于动态连通性问题。
-
支持两个主要操作:
union(p, q)
:合并两个集合find(x)
:查询某个节点的根节点(即所属集合代表)
-
优化技巧:
- 路径压缩(Path Compression)
- 按秩合并(Union by Rank)
-
应用场景:判断图的连通性、最小生成树(如 Kruskal 算法)、动态连通性维护等。
并查集模板
class UF: # 连通分量个数 _count: int # 每个节点的父节点 parent: List[int]
def __init__(self, n: int): self._count = n self.parent = [i for i in range(n)]
# 合并两个集合 def union(self, p: int, q: int): rootP = self.find(p) rootQ = self.find(q) if rootP == rootQ: return self.parent[rootQ] = rootP self._count -= 1
# 判断是否连通 def connected(self, p: int, q: int) -> bool: return self.find(p) == self.find(q)
# 查找根节点,带路径压缩 def find(self, x: int) -> int: if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x]
# 返回当前连通分量个数 def count(self) -> int: return self._count
卡码网:107. 寻找存在的路径
思路:
- 使用并查集将所有边合并处理,判断
source
和destination
是否属于同一集合。 - 注意节点编号从 1 开始,代码中需要减 1 进行索引转换。
import sysfrom typing import List
class UF: _count: int parent: List[int]
def __init__(self, n: int): self._count = n self.parent = [i for i in range(n)]
def union(self, p: int, q: int): rootP = self.find(p) rootQ = self.find(q) if rootP == rootQ: return self.parent[rootQ] = rootP self._count -= 1
def connected(self, p: int, q: int) -> bool: return self.find(p) == self.find(q)
def find(self, x: int) -> int: if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x]
def count(self) -> int: return self._count
def main(): data = sys.stdin.read().strip().split() N, M = int(data[0]), int(data[1]) edges = data[2:2 + 2*M] source, destination = int(data[2 + 2*M]), int(data[3 + 2*M])
uf = UF(N) # 并查集节点从 0 开始,题中编号从 1 开始 for i in range(0, 2*M, 2): s, t = int(edges[i]) - 1, int(edges[i+1]) - 1 uf.union(s, t)
# 判断 source 和 destination 是否连通 if uf.connected(source - 1, destination - 1): print(1) else: print(0)
if __name__ == "__main__": main()
代码随想录算法训练营第四十七天 | 图论 Part05
https://fuwari.vercel.app/posts/code_musings_day_forty-seven/