修改数组/并查集

修改数组/并查集_第1张图片

修改数组/并查集_第2张图片 

 题解:

首先补充一下并查集的知识:

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

  • 合并(Merge):把两个不相交的集合合并为一个集合,把两个元素节点的祖宗节点合一起就行了
  • 查询(Find):查询两个元素是否在同一个集合中.,看两个集合的祖宗节点是否一致就行了

 给出代码模板:

首先解释一下模板中变量的含义,f[i]表示元素i的父节点,find(i)为查询函数,输出的是i的祖宗节点,即根节点

1.父节点初始化:

f=[i for i in range(i+1)]

 即每个节点的父节点一开始就是她本身

2.查询:

def find(n):
    if f[n]==n:#如果父节点就是本身,那么这个节点就是祖宗根节点
        return n
    else:
        f[n]=find(f[n])#如果父节点不是本身,那么祖宗根节点就通过不断地递归寻找得到
        return f[n]

 3.合并

def merge(x,y):
    xx=find(x)
    yy=find(y)
    if xx!=yy:#如果x的祖宗根节点和y的祖宗根节点不一致,那么让这俩祖宗根节点的父节点一样就行了
        f[xx]=f[yy]

 给个模板例题:

修改数组/并查集_第3张图片

 代码:

def find(n):
    if f[n]==n:
        return n
    else:
        f[n]=find(f[n])
        return f[n]
def merge(x,y):
    xx=find(x)
    yy=find(y)
    if xx!=yy:
        f[xx]=f[yy]
n,m=map(int,input().split())
f=[0]*(n+1)
for i in range(1,n+1):
    f[i]=i
for i in range(m):
    z,x,y=map(int,input().split())
    if z==1:
        merge(x,y)
    if z==2:
        if find(x)==find(y):
            print("Y")
        else:
            print("N")

好,那我们来看这个题,暴力梭哈是可以做的,可是严重超时,这种情况下,处理一些不相交集合的合并及查询问题,查并集算法能大大减少时间

这里的思想就是首先判断这个数是否已经出现过,只需要判断它的父节点是否是它本身:

1.如果x没有出现过,结果就是他自己,那么根据我们初始化f[x]的定义,结果就是f[x]

2.如果x出现过,那么f[x]!=x,就直接寻找x的祖宗根节点find(x),这个答案就是最终答案,出现了你得做一个标记吧,这个标记就可以用到合并函数,merge(x,x+1),什么意思呢?x+1的初始化祖宗根节点肯定是它本身,合并函数运行之后x的祖宗根节点就成了x+1的祖宗根节点,祖宗根节点是最终答案,那么不正符合题意吗?x出现一次之后要+1

 

你可能感兴趣的:(蓝桥杯真题,算法,数据结构)