Python之并查集 洛谷 蓝桥杯(1)

简介: Python之并查集 洛谷 蓝桥杯

同时正在备战蓝桥杯 题解如有不足请多批评指正

大一双非本科在读

目标是进大厂



洛谷:亲戚关系 题目链接

image.png

问题分析:这是一道考察并查集的经典例题。

何为并查集?并查集是一种(树型)数据结构 ,用于处理一些不相交集合的合并查询问题。

思想:用一个数组表示了整片森林,树的根节点唯一标识了一个集合,我们只要找到了某个元素的的树根,就能确定它在哪个集合里。例如给出数组parent=[0,1,5,1,3,1],parent[i]代表结点i的父结点(很形象吧!?)


观察数组,我们知道:parent[2]=5 ,说明了结点2的父节点是5


再来:parent[5]=1,说明了结点5的父节点是1


再来:parent[1]=1,说明了结点1的父节点是1


对上面这行可能有疑惑:我们先记住,若parent[i]=i  则i是一个集合内的根节点


那么他有什么作用:如果一个结点j 它的父节点的父节点的父节点的父节点.....是i


说明了j和它的父节点和它的父节点的父节点和....一共这么多结点,对于每一个结点,都可以访问到i结点。我们不如把它叫做祖先(能够访问 类似于 含有血缘关系,你和你的祖先,你的父亲的祖先,你的父亲的父亲的祖先都有血缘关系。)


因此这么多结点就构成了一个集合(代表集合的对象是根节点(祖先))


所以对于刚刚提到的数组,由于结点5可以访问到祖先>>1,所以5和1有血缘关系,即5属于祖先1代表的集合,由于结点2的父节点是5,所以它可以通过父节点5访问到祖先>>1,所以2和1有血缘关系,即2属于祖先1代表的集合。


因此我们要判断两个结点是否属于同一个集合,可以借助访问各自的祖先加以判断。


如果祖先相同,那么属于同一集合,否则不属于同一集合。


对于上述数组结点0和结点1就不属于同一集合


所以下面给出访问祖先的代码:(关于优化下面会阐述)

def find_root(x):
    while x!=parent[x]:3如果不是祖先 就访问自己的父节点
        x=parent[x]
    return x


那么上面这段代码就是代表了并查集的思想之一:查询


那么下面我们研究并查集的另一个思想:合并


再次给出上面那个例子parent=[0,1,5,1,3,1]


我们知道结点1,2,3,4,5同属于一个集合(用结点1来标识)


由于parent[0]=0 说明0是一个集合的祖先,这个集合用结点0来标识


由于以结点0为代表的集合元素个数为1,比较特殊,我们不妨给他(集合)添加两个结点


分别是结点6,结点7,因此parent=[0,1,5,1,3,1,0,0]


所以现在 结点0,6,7同属于一个集合(用结点0来标识)


下面研究合并,何为合并?就是将两个集合变为为一个集合


容易想到,我们可以把结点0(祖先)作为结点1的子结点,换句话说,把结点1作为结点0的父节点。


那么这样子有什么用:我们知道用结点0来标识的集合中的结点,都可以访问到结点0,现在结点0又可以访问到结点1,所以用结点0来标识的集合中的结点,都可以访问到结点1,因此用结点1来标识的集合 结点数目扩大了! 这不正达到了我们想要的效果吗?


简言之 集合A和集合B原本分属两大家族,把A的祖先作为B祖先的孩子,因而集合A和B中的所有结点都有了血缘关系,实现了家族合并。

所以下面给出合并的代码:


def union(x,y):#合并

   x_root,y_root=find(x),find(y)

   parent[x_root]=y_root#一般的x_root!=y_root,直接合并过去

                           #如果x_root=y_root,合并本身,没有发生任何变化

所以 代码就可写出了:

def find_root(x):
    while x!=parent[x]:
        x=parent[x]
    return x
def union(x,y):
    x_root=find_root(x)
    y_root=find_root(y)
    parent[x_root]=y_root
n,m,p=map(int,input().strip().split())
parent=[i for i in range(n+1)]#初始化
for i in range(m):#h合并
    tmp=list(map(int,input().strip().split()))
    union(tmp[0],tmp[1])
for j in range(n):#判断
    tmp=list(map(int,input().strip().split()))
    if find_root(tmp[0])==find_root(tmp[1]):
        print('Yes')
    else:
        print('No')

image.png



目录
相关文章
|
2月前
|
Python
蓝桥杯练习题(一):Python组之入门训练题
这篇文章是关于蓝桥杯Python组的入门训练题,包括Fibonacci数列、圆的面积、序列求和和A+B问题的具体代码实现和样例输出。
143 0
|
2月前
|
算法 开发者 计算机视觉
燃爆全场!Python并查集:数据结构界的网红,让你的代码炫酷无比!
在编程的世界里,总有一些数据结构以其独特的魅力和高效的性能脱颖而出,成为众多开发者追捧的“网红”。今天,我们要介绍的这位明星,就是Python中的并查集(Union-Find)——它不仅在解决特定问题上大放异彩,更以其优雅的设计和强大的功能,让你的代码炫酷无比,燃爆全场!
41 0
|
2月前
|
存储 机器学习/深度学习 算法
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
蓝桥杯Python编程练习题的集合,涵盖了从基础到提高的多个算法题目及其解答。
128 3
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
|
2月前
|
人工智能 Python
蓝桥杯练习题(四):Python组之历届试题三十题
关于蓝桥杯Python组历届试题的三十个练习题的总结,包括题目描述、输入输出格式、样例输入输出以及部分题目的解题思路和代码实现。
50 0
蓝桥杯练习题(四):Python组之历届试题三十题
|
2月前
|
Python
智慧之光!Python并查集:点亮你的编程思维,让复杂问题迎刃而解!
并查集以其简洁而强大的功能,成为了解决特定类型问题的首选工具。在编程的旅途中,掌握并查集不仅能帮助我们解决眼前的难题,更能点亮我们的编程思维,让我们在面对更复杂的问题时也能游刃有余。希望今天的分享能激发你对并查集的兴趣,让你在未来的编程道路上走得更远、更稳。
34 1
|
2月前
|
存储 算法 Python
火箭般的提升!学会Python并查集,让你的算法能力飞跃新高度!
火箭般的提升!学会Python并查集,让你的算法能力飞跃新高度!
37 1
|
3月前
|
Python
逆天改命!掌握Python并查集,数据结构难题从此不再是你的痛!
在编程旅程中,遇到棘手的数据结构难题是否让你苦恼?别担心,Python并查集(Union-Find)是你的得力助手。这是一种高效处理不相交集合合并及查询的数据结构,广泛应用于网络连通性、社交网络圈子划分等场景。通过维护每个集合的根节点,它实现了快速合并与查询。本文将介绍并查集的基本概念、应用场景以及如何在Python中轻松实现并查集,帮助你轻松应对各种数据结构挑战。
40 3
|
3月前
|
算法 计算机视觉 Python
Python并查集大揭秘:让你在算法界呼风唤雨,秒杀一切复杂场景!
在编程与算法的广袤天地中,总有一些工具如同神兵利器,能够助你一臂之力,在复杂的问题前游刃有余。今天,我们就来深入探讨这样一件神器——Python并查集(Union-Find),看看它是如何让你在算法界呼风唤雨,轻松应对各种复杂场景的。
82 2
|
2月前
|
存储 机器学习/深度学习 算法
蓝桥杯练习题(二):Python组之基础练习三十题
蓝桥杯Python编程练习题的集合,包含了三十个不同难度的编程题目,覆盖了基础语法、数据结构和算法等领域。
52 0
|
3月前
|
Python
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
34 0