[洛谷Luogu]P1141 01迷宫[联通块 并查集]

通过并查集解决洛谷P1141 01迷宫问题,计算每个点所在的连通块大小。采用路径压缩和按节点大小合并优化,降低并查集复杂度至近似O(n^2)。
摘要由CSDN通过智能技术生成

题目链接

大致题意

相邻格子不同为连通,计算每个点所在的连通块大小。

想法

我采用了并查集的做法。
开一个辅助数组记录连通块大小,每次合并的时候更新父亲节点的大小即可。

一个点先与它上面的点判定,若判定连通则加入上方点所属的块中。
再与左边的点判定,若连通则再将两个块合并。

总体复杂度 O ( n 3 ) O(n^3) O(n3),其中并查集不加优化复杂度为 O ( n ) O(n) O(n),使用路径压缩+按节点大小合并优化并查集,将并查集复杂度降低为近似 O ( 1 ) O(1) O(1),总体复杂度近似为 O ( n 2 ) O(n^2) O(n2)

并查集优化

路径压缩

每次查找的时候,将路径上的所有儿子的父亲改写为最原始的祖宗。这样下次就可以直接找到祖宗。
实现:

inline int find(const int &x)
{
   
    return fa[x] == x ? x : fa[x] = find(fa[x]);//路径压缩
}

通俗写法:

inline int find(const int &x)
{
   
    if(fa[x] == x)//找到无父亲的节点,即为祖宗
    	return x;
    fa[x] = find(fa[x]);
    return fa[x];
}

按秩合并

思考:
有2个块需要合并,那么将小块接在大块的后面能够让整体复杂度更优。
可以将每个祖宗及其所有儿子看做一棵树,那么节点到根的距离就是查找父亲需要的次数。
将小树并入大树,可以避免树的深度过深。
这个rnk数组保存的是树的深度的上界。
通常写法:

const int maxn = 10000000;
int rnk[maxn],fa[maxn];//rnk为该节点所在子树的深度
inline void unite(const int &x
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值