用python代码实现.使用并查集思想求解问题::有n个方块(n<=30000),p组操作(p<=100000),操作有两种,M a b 将含有a的堆放在包含b的堆上,还有一种是 C a统计a下面有多少个方块 思路:带权并查集,一堆中最顶上的方块作为父节点
时间: 2024-02-05 21:12:55 浏览: 137
以下是用Python实现的带权并查集求解该问题的代码:
```python
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.weight = [0] * n
def find(self, x):
if self.parent[x] != x:
p = self.find(self.parent[x])
self.weight[x] += self.weight[self.parent[x]]
self.parent[x] = p
return self.parent[x]
def merge(self, x, y):
px, py = self.find(x), self.find(y)
if px == py:
return
self.parent[px] = py
self.weight[px] = self.weight[y] - self.weight[x] + 1
def diff(self, x, y):
if self.find(x) != self.find(y):
return -1
return abs(self.weight[x] - self.weight[y])
n, p = map(int, input().split())
uf = UnionFind(n)
for i in range(p):
op, a, b = input().split()
a, b = int(a)-1, int(b)-1
if op == 'M':
uf.merge(a, b)
else:
print(uf.diff(a, b))
```
首先定义了一个带权并查集类`UnionFind`,包含`parent`和`weight`两个数组,分别表示每个元素的父节点和与父节点的重量差。在`find`方法中,使用递归查找父节点,并在查找过程中累加重量差;在`merge`方法中,先查找两个元素的根节点,然后将其中一个根节点指向另一个根节点,并更新重量差;在`diff`方法中,如果两个元素不在同一集合中,则返回-1,否则返回它们的重量差的绝对值。
接下来,读入n和p,创建一个带权并查集对象`uf`。然后进行p次操作,如果是'M'操作,则调用`merge`方法合并两个元素的集合;否则调用`diff`方法计算两个元素的重量差,并输出结果。
阅读全文