作用:检查图上面是否存在环

image.png
先将连通的节点加入集合,如果再选中的边的两个顶点已经在集合里了,说明出现环


合并算法:
1.一维数组image.png 全是 -1 初始化表示独立
parent[1] = 0 说明1的父节点是0
parent[2]= 0 说明2的父节点也是0
012三个节点就可以连接起来

2.如何连接两棵树(并)
image.png
为了不形成断层和路径过长
分别找到父节点,然后连接(查)image.png

结论:构造出parent数组之后,如果两个节点根节点一样,则说明有环
image.png


image.png
寻找x, y的根节点 x_root, y_root然后合并

分为两个函数find_root(), union() 找根节点和合并()查和并

  1. n = len(verticices)
  2. parent = [-1] * n
  3. ## 找到根节点(-1)为止
  4. def find_root(x, parent):
  5. x_root = x
  6. while parent[x_root] != -1:
  7. x_root = parent[x_root]
  8. return x_root
  9. ## return: True/False
  10. def union(x, y, parent):
  11. x_root = find_root(x)
  12. y_root = find_root(y)
  13. if x_root == y_root:
  14. return False
  15. parent[x_root] = y_root
  16. return True

union算法问题:如果图链特别长,查找parent数组复杂度将会变成o(logn)?复杂度
引进新变量 Rank
image.png

  1. n = len(verticices)
  2. parent = [-1] * n
  3. rank = [0] * n
  4. ## 找到根节点(-1)为止
  5. def find_root(x, parent):
  6. x_root = x
  7. while parent[x_root] != -1:
  8. x_root = parent[x_root]
  9. return x_root
  10. ## return: True/False
  11. def union(x, y, parent, rank):
  12. x_root = find_root(x)
  13. y_root = find_root(y)
  14. if x_root == y_root:
  15. return False
  16. ## 路径压缩算法
  17. if rank[x_root] > rank[y_root]:
  18. parent[y_root] = x_root
  19. elif rank[y_root] > rank[x_root]:
  20. parent[x_root] = y_root
  21. else:
  22. parent[y_root] = x_root
  23. rank[x_root] += 1
  24. return True

总结: parent[], rank []
find_root()
union() + 路径压缩


模板

  1. class UnionFind:
  2. def __init__(self):
  3. """
  4. 记录每个节点的父节点
  5. """
  6. self.father = {}
  7. def find(self,x):
  8. """
  9. 查找根节点
  10. 路径压缩
  11. """
  12. root = x
  13. while self.father[root] != None:
  14. root = self.father[root]
  15. # 路径压缩
  16. while x != root:
  17. original_father = self.father[x]
  18. self.father[x] = root
  19. x = original_father
  20. return root
  21. def merge(self,x,y,val):
  22. """
  23. 合并两个节点
  24. """
  25. root_x,root_y = self.find(x),self.find(y)
  26. if root_x != root_y:
  27. self.father[root_x] = root_y
  28. def is_connected(self,x,y):
  29. """
  30. 判断两节点是否相连
  31. """
  32. return self.find(x) == self.find(y)
  33. def add(self,x):
  34. """
  35. 添加新节点
  36. """
  37. if x not in self.father:
  38. self.father[x] = None
  39. 作者:MiloMusiala
  40. 链接:https://leetcode-cn.com/problems/evaluate-division/solution/pythonbing-cha-ji-fu-mo-ban-by-milomusia-kfsu/
  41. 来源:力扣(LeetCode
  42. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。