热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python之并查集洛谷蓝桥杯

同时正在备战蓝桥杯题解如有不足请多批评指正大一双非本科在读目标是进大厂洛谷:亲戚关系题目链接问题分析:这是一道考察并查集的经典例题。何为并查集ÿ

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

大一双非本科在读

目标是进大厂 

洛谷:亲戚关系 题目链接

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

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

思想:用一个数组表示了整片森林,树的根节点唯一标识了一个集合,我们只要找到了某个元素的的树根,就能确定它在哪个集合里。

例如给出数组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 xdef union(x,y):x_root=find_root(x)y_root=find_root(y)parent[x_root]=y_rootn,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')

 但是这样超时 所以需要进行优化:

先分析超时的原因:还是利用上面给出的数组parent=[0,1,5,1,3,1,0,0](未合并)

我们可以画出下面这样的关系图:

 所以科学家们给出了一种方法:路径压缩。

简言之,对于上图,比如在访问4的根节点的时候,经过图中标识的''很长''一段路径,这一段路径由许许多多的结点构成,它们有一个共同特点就是根节点都是1,那么路径压缩要做的就是把这条路径上的所有结点的父节点设为结点1

这样子的作用:比如我下一次查询结点3的根节点的时候,只需要1次,原来需要9999次!

def find_root(x):#返回根节点if x!=parent[x]:#只要不是根节点parent[x]=find_root(parent[x])#修改父节点为根结点return parent[x]#返回根节点(父节点)

 第一次接触路径压缩如果不太好理解,可以先和小郑一样把这个模板记下来~


n,m,p=map(int,input().strip().split())parent=[i for i in range(n+1)]def find_root(x):#返回根节点if x!=parent[x]:#只要不是根节点parent[x]=find_root(parent[x])#把x的父节点设为根节点return parent[x]def union(x,y):x_root=find_root(x)y_root=find_root(y)parent[x_root]=y_rootfor i in range(m):tmp=list(map(int,input().strip().split()))union(tmp[0],tmp[1])for j in range(p):tmp=list(map(int,input().strip().split()))if find_root(tmp[0])==find_root(tmp[1]):print('Yes')else:print('No')

 

 可见路径压缩帮助我们优化了算法

蓝桥杯真题实战:七段码(第十一届试题E填空压轴)>>考察并查集

代码设计分析:题目就是在问一个连通性问题,从7条边选几个出来判断是不是连通图。

也就是判断是不是属于同一个集合的问题。首先明确一点,并查集两大功能:查找与合并。要先合并,再查找(没有合并一个集合那拿什么来查找?)。所以,相当于我们要先构建亲戚关系网,最后判断所有结点的祖先是否都是同一个,如果是则连通,否则不连通。

那么构建亲戚关系的条件:如果两个顶点直接相连,那么把那个点所属的集合与另外一个点所属的集合合并。当所有的点合并完了,只需要遍历所有的点的祖先,判断是否都是同一个,如果是,大功告成,count加1

def find_root(x):if x!=parent[x]:parent[x]=find_root(parent[x])return parent[x]def union(x,y):x_root,y_root=find_root(x),find_root(y)if x_root!=y_root:parent[x_root]=y_rootedge=[[0]*7 for i in range(7)]#设一个0号进去,无边与其相连l=[0,1,2,3,4,5,6]
edge[0][1]=edge[0][2]=edge[1][3]=edge[1][4]=edge[2][3]=1
edge[3][4]=edge[3][5]=edge[4][6]=edge[5][6]=edge[2][5]=1#有边相连记作1for i in range(7):for j in range(7):edge[i][j]=max(edge[i][j],edge[j][i])#无向图对称import itertoolscount=0for i in range(1,8):#灯泡数目for j in itertools.combinations(l,i):#比如[(1,2,3),[1,2,4]]parent=[i for i in range(7)]#判断两两是否连通for k in range(0,i):for p in range(k+1,i):if edge[j[k]][j[p]]==1:#如果连通,合并union(j[k],j[p])for m in range(i-1):#判断属于是否同一集合(最终所有的)if find_root(j[m])!=find_root(j[m+1]):breakelse:print(j)#显示符合条件的数据,可删去count+=1
print(count)
#答案80

 我是小郑 正在奔赴热爱 奔赴山海!


推荐阅读
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 本文介绍了一个Python函数same_set,用于判断两个相等长度的数组是否包含相同的元素。函数会忽略元素的顺序和重复次数,如果两个数组包含相同的元素,则返回1,否则返回0。文章还提供了函数的具体实现代码和样例输入输出。 ... [详细]
  • tcpdump 4.5.1 crash 深入分析
    tcpdump 4.5.1 crash 深入分析 ... [详细]
  • 基于词向量计算文本相似度1.测试数据:链接:https:pan.baidu.coms1fXJjcujAmAwTfsuTg2CbWA提取码:f4vx2.实验代码:imp ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • 在本教程中,我们将看到如何使用FLASK制作第一个用于机器学习模型的RESTAPI。我们将从创建机器学习模型开始。然后,我们将看到使用Flask创建AP ... [详细]
  • 获取时间的函数js代码,js获取时区代码
    本文目录一览:1、js获取服务器时间(动态)2 ... [详细]
  • 数学建模入门python绘制频率直方图
    文章目录例题数据处理绘图操作调用演示例题数据处理将以下的数据保存到磁盘上17275169551696417165167471716216867165521696216865 ... [详细]
author-avatar
帝·姬
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有