社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
并查集算法是通过一个一维数组来实现的,其本质是维护一个森林。
刚开始的时候,森林的每个点都是孤立的,也可以理解为一颗只有一个结点的树,也就是说每个结点的父结点都是它本身。
# 这是初始化函数
def init():
global n
for i in range(1,n+1):
f[i] = i
return
可以使用递归函数来进行寻找父结点,在找父结点的过程中将过程中的结点指向父结点。这也被称为“擒贼先擒王”原则、
# 这是找父节点的递归函数
def getf(v):
if f[v] == v:
return v
else:
# 这里是路径压缩,每次在函数返回的时候顺便把论述遇到的人的‘boss’
# 改为最后找到的祖宗编号,这样可以提高今后找到犯罪团伙的最高领导人的速度
f[v] = getf(f[v])
return f[v]
合并的过程其实是“认爹”的过程,在该过程中要遵循“靠左”原则和“擒贼先擒王”原则。
# 这是两个子集合并的函数
def merge(v, u):
t1 = getf(v)
t2 = getf(u)
if t1 != t2:
f[t2] = t1 # 这里使用靠左原则,即把右边的集合作为左边集合的子集
return
n, sum = 0, 0
f = [0 for i in range(1000)]
# 这是初始化函数
def init():
global n
for i in range(1,n+1):
f[i] = i
return
# 这是找父节点的递归函数
def getf(v):
if f[v] == v:
return v
else:
# 这里是路径压缩,每次在函数返回的时候顺便把论述遇到的人的‘boss’
# 改为最后找到的祖宗编号,这样可以提高今后找到犯罪团伙的最高领导人的速度
f[v] = getf(f[v])
return f[v]
# 这是两个子集合并的函数
def merge(v, u):
t1 = getf(v)
t2 = getf(u)
if t1 != t2:
f[t2] = t1 # 这里使用靠左原则,即把右边的集合作为左边集合的子集
return
if __name__ == '__main__':
# print("test")
n, m = map(int,input().split())
init()
# 合并团伙
for i in range(1,m+1):
x,y = map(int,input().split())
merge(x,y)
# 寻找独立的团伙
for i in range(1,n+1):
print(f[i], end = ' ')
if f[i] == i:
sum += 1
print()
print(sum)
'''
测试样例
10 9
1 2
3 4
5 2
4 6
2 6
8 7
9 7
1 6
2 4
'''
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!