deffind(self,x:int)->int:"""查找 x 的根节点,并进行路径压缩"""ifself.parent[x]!=x:# 递归查找根节点,并将路径上的所有节点直接连接到根节点self.parent[x]=self.find(self.parent[x])returnself.parent[x]
defunion(self,x:int,y:int)->bool:"""合并 x 和 y 所在的集合"""root_x=self.find(x)root_y=self.find(y)# 已经在同一集合中ifroot_x==root_y:returnFalse# 按秩合并:将秩小的树连接到秩大的树下ifself.rank[root_x]<self.rank[root_y]:self.parent[root_x]=root_yelifself.rank[root_x]>self.rank[root_y]:self.parent[root_y]=root_xelse:# 秩相同时,任意选择一个作为根,并增加其秩self.parent[root_y]=root_xself.rank[root_x]+=1self.count-=1returnTrue
classUnionFind:def__init__(self,n:int):self.parent=list(range(n))self.size=[1]*n# size[i] 表示以 i 为根的集合大小defunion(self,x:int,y:int)->bool:root_x,root_y=self.find(x),self.find(y)ifroot_x==root_y:returnFalse# 按大小合并ifself.size[root_x]<self.size[root_y]:self.parent[root_x]=root_yself.size[root_y]+=self.size[root_x]else:self.parent[root_y]=root_xself.size[root_x]+=self.size[root_y]returnTruedefget_size(self,x:int)->int:"""获取 x 所在集合的大小"""returnself.size[self.find(x)]
classUndoableUnionFind:def__init__(self,n:int):self.parent=list(range(n))self.rank=[0]*nself.history=[]# 记录操作历史defunion(self,x:int,y:int)->bool:root_x,root_y=self.find(x),self.find(y)ifroot_x==root_y:returnFalse# 记录操作前的状态ifself.rank[root_x]<self.rank[root_y]:self.history.append((root_x,self.parent[root_x],self.rank[root_x]))self.parent[root_x]=root_yelifself.rank[root_x]>self.rank[root_y]:self.history.append((root_y,self.parent[root_y],self.rank[root_y]))self.parent[root_y]=root_xelse:self.history.append((root_y,self.parent[root_y],self.rank[root_y]))self.history.append((root_x,self.parent[root_x],self.rank[root_x]))self.parent[root_y]=root_xself.rank[root_x]+=1returnTruedefundo(self)->None:"""撤销上一次 union 操作"""ifnotself.history:returnnode,parent,rank=self.history.pop()self.parent[node]=parentself.rank[node]=rank
classWeightedUnionFind:def__init__(self,n:int):self.parent=list(range(n))self.weight=[0]*n# weight[i] 表示 i 到 parent[i] 的权值deffind(self,x:int)->int:ifself.parent[x]!=x:root=self.find(self.parent[x])# 更新权值:累加路径上的权值self.weight[x]+=self.weight[self.parent[x]]self.parent[x]=rootreturnself.parent[x]defunion(self,x:int,y:int,w:int)->bool:"""合并 x 和 y,x 到 y 的权值为 w"""root_x,root_y=self.find(x),self.find(y)ifroot_x==root_y:returnFalse# 计算 root_x 到 root_y 的权值self.parent[root_x]=root_yself.weight[root_x]=self.weight[y]-self.weight[x]+wreturnTruedefdiff(self,x:int,y:int)->int:"""返回 x 到 y 的权值差"""ifself.find(x)!=self.find(y):returnfloat('inf')# 不在同一集合returnself.weight[x]-self.weight[y]