并查集 蓝桥杯例题+详解

文章介绍了并查集数据结构在处理合根植物连根问题中的应用,涉及初始化、查询、合并操作,以及如何通过路径压缩优化效率。通过实例演示了如何使用并查集计算给定种植园中合根植物的数量。
摘要由CSDN通过智能技术生成

并查集

蓝桥杯例题合根植物

问题描述

w 星球的一个种植园,被分成 m×n 个小格子(东西方向 m 行,南北方向 n 列)。每个格
子里种了—株合根植物。
这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物
合成为—体。
如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植
物吗?

输入格式

第—行,两个整数 m,n,用空格分开,表示格子的行数、列数(1<m,n ≤1000)。
接下来一行,一个整数 k(0<k<105),表示下面还有 k 行数据。
接下来 k 行,每行两个整数 a,b,表示编号为α的小格子和编号为 b 的小格子合根了。
格子的编号—行—行,从上到下,从左到右编号。
比如:5×4 的小格子,编号:

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 16

17 18 19 20

输出格式

输出植物数量。

样例输入

5 4

16

2 3

1 5

5 9

4 8

7 8

9 10

10 11

11 12

10 14

12 16

14 18

17 18

15 19

19 20

9 13

13 17

样例输出

5

介绍:

并查集(Union-find Sets)是一种非常精巧而实用的数据结构,他主要用于处理一些不相交集合的合并问题。一些常见的用途有求连通子图、最小生成树的Kruskal算法和求最近公共祖先(LCA)等。

并查集的主要操作

1.初始化
创建一个数组(列表)用来存储每个元素的父节点,一开始我们先讲他们的父节点设为本身。每一个元素对应这一个列表中存储的一个节点,节点对应相应的父元素,而父元素的列表中也存储着相应的节点,可以通过元素与列表的二元对应和依次递归实现后续查和并的操作

fa=[0 for i in range(1,m*n+1)]
for i in range(1,m*n+1):              #因为题中序号没有0是从1开始所以在此从1开始
    fa[i-1]=i                         #下文给出的代码据此机制做出了相应调整

2.查询find
找到元素的祖先直接返回
此处根据题目示例给出代码

def find(x):                       #定义函数find查找根节点
if fa[x-1]==x:                     #递归出口,当到达了根位置,就返回根
    return x
else:
    return find(fa[x-1])           #递归,不断向上查找,直到达到根

这是初级版本,没用运用路径压缩,当处理的数量级很大时,需要进行路径压缩从而提高
执行效率

def find(x):               
if fa[x-1]==x:
    return x
else:
    fa[x-1]=find(fa[x-1])          #压缩路径,使元素对应列表的存储内容改为根节点
    return fa[x-1]

3.合并union

def merge(x,y):
r_x = find(x)        #找到x的祖先
r_y = find(y)        #找到y的祖先
if r_x!=r_y:         #判断x,y是否在一个集合里(即是否用共同的祖先)
    fa[r_x-1]=r_y    #使x对应的列表指向y,从而合并两个集合
    return 0

核心思想已经掌握,接下来给出完整代码

def find(x):               
    if fa[x-1]==x:
        return x
    else:
        fa[x-1]=find(fa[x-1])
        return fa[x-1]
def merge(x,y):
    r_x = find(x)
    r_y = find(y)
    if r_x!=r_y:
        fa[r_x-1]=r_y
        return 0

m,n=map(int,input().split())
fa=[0 for i in range(1,m*n+1)]
for i in range(1,m*n+1):
    fa[i-1]=i

k=int(input())
for i in range(k):
    p,q=map(int,input().split())
    merge(p,q)
count=0
li=[]
for i in range(1,m*n+1):
    t=find(fa[i-1])
    if t not in li:
        li.append(t)
        count+=1
print(count)

生命有点像一阵风,虽然我们看不见,却能感受风吹来的那一刻。 —肖纳·英尼斯

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值