• 【python数据结构算法】并查集


    前言🍉

            并查集被很多OIer认为是最简洁而优雅的数据结构之一,主要用于解决一些元素分组的问题。它管理一系列不相交的集合,并支持两种操作:

    • 合并(Union):把两个不相交的集合合并为一个集合。
    • 查询(Find):查询两个元素是否在同一个集合中。

    并查集的重要思想在于,用集合中的一个元素代表集合。我曾看过一个有趣的比喻,把集合比喻成帮派,而代表元素则是帮主。接下来我们利用这个比喻,看看并查集是如何运作的。

    最开始,所有大侠各自为战。他们各自的帮主自然就是自己。(对于只有一个元素的集合,代表元素自然是唯一的那个元素)

    现在1号和3号比武,假设1号赢了(这里具体谁赢暂时不重要),那么3号就认1号作帮主(合并1号和3号所在的集合,1号为代表元素)

    现在2号想和3号比武(合并3号和2号所在的集合),但3号表示,别跟我打,让我帮主来收拾你(合并代表元素)。不妨设这次又是1号赢了,那么2号也认1号做帮主。 


    现在我们假设4、5、6号也进行了一番帮派合并,江湖局势变成下面这样: 

    现在假设2号想与6号比,跟刚刚说的一样,喊帮主1号和4号出来打一架(帮主真辛苦啊)。1号胜利后,4号认1号为帮主,当然他的手下也都是跟着投降了。

    好了,比喻结束了。如果你有一点图论基础,相信你已经觉察到,这是一个状的结构,要寻找集合的代表元素,只需要一层一层往上访问父节点(图中箭头所指的圆),直达树的根节点(图中橙色的圆)即可。根节点的父节点是它自己。我们可以直接把它画成一棵树:

     用这种方法,我们可以写出最简单版本的并查集代码。


    题目1:合并集合🍉

    描述🎈


    要求 🎈


     样例🎈


    复习模板 🎈


    1. # dataset
    2. def load_dataset():
    3. n, m = map(int, input().split())
    4. opts = []
    5. nodes = []
    6. for _ in range(m):
    7. opt, u, v = input().split()
    8. u = int(u)
    9. v = int(v)
    10. opts.append(opt)
    11. nodes.append([u, v])
    12. return n, m, opts, nodes
    13. # model
    14. def union_find_set(x):
    15. if p[x] != x:
    16. p[x] = union_find_set(p[x])
    17. return p[x]
    18. if __name__ == "__main__":
    19. n, m, opts, nodes = load_dataset()
    20. p = [n for n in range(n + 1)]
    21. for i in range(m):
    22. iter_opt = opts[i]
    23. u, v = nodes[i]
    24. eu = union_find_set(u)
    25. ev = union_find_set(v)
    26. if iter_opt == "M":
    27. if eu != ev:
    28. p[eu] = p[ev]
    29. elif iter_opt == "Q":
    30. if eu == ev:
    31. print('Yes')
    32. else:
    33. print('No')

    题目2: 连通块中点的数量🍉

    描述 🎈


     要求🎈


    样例 🎈


     复习模板🎈


    1. '''
    2. # #AC Code((连通块中点的数量)# #
    3. '''
    4. def find(x):
    5. if p[x] != x:
    6. p[x] = find(p[x])
    7. return p[x]
    8. n, m = map(int, input().split())
    9. p = [_ for _ in range(n+1)]
    10. s = [1] * (n + 10)
    11. Querry = []
    12. for _ in range(m):
    13. Querry.append(input().split())
    14. for Q in Querry:
    15. if Q[0] == 'C':
    16. a, b = int(Q[1]), int(Q[2])
    17. if find(a) != find(b):
    18. s[find(b)] += s[find(a)] # 先加上点的数量 不然都合并了就失去原来被合并的值了因为a,b的Father都以一样了
    19. p[find(a)] = find(b)
    20. elif Q[0] == 'Q1':
    21. a, b = int(Q[1]), int(Q[2])
    22. if find(a) == find(b):
    23. print("Yes")
    24. else:
    25. print("No")
    26. else:
    27. x = int(Q[1])
    28. print(s[find(x)])
  • 相关阅读:
    HDU- 1166 敌兵布阵 - 线段树
    uni-app开发微信小程序时u-view自定义样式不生效
    Oracle-表空间基于时间点恢复(TSPITR)
    如何衡量软件系统的复杂度(一)
    Spring Boot 2.7.0发布,2.5停止维护,节奏太快了吧
    大四web前端网页制作课作业——HTML+CSS+JavaScript仿小米手机商城网站(37页)
    一种基于分子结构的密码算法的设计方案
    【在凸多边形的图像中查找顶点】估计具有已知顶点数的像素化凸多边形角点研究(Matlab代码实现)
    Small RTOS51 学习笔记(1)使用 RTOS 的好处
    SpringMVC第六阶段:数据在域中的保存(02)
  • 原文地址:https://blog.csdn.net/qq_51831335/article/details/127818392