并查集 水题

本文详细介绍了并查集算法的基本概念、实现原理及其在解决实际问题中的应用。通过具体的代码示例,展示了如何使用并查集来高效地解决连接性和分组问题。适合初学者快速掌握并查集算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


题目链接





#include <iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<stack>
#include<queue>
#include<vector>
#include<stdlib.h>

using namespace std;
const int INF =2100000000;
int pre[1010];
void Init(int n)
{
    for(int i=0;i<=n;i++)
        pre[i]=i;
}
int finds(int x)
{
    return pre[x]==x?x:pre[x]=finds(pre[x]);
}
void jion(int x,int y)
{
    int fx=finds(x);
    int fy=finds(y);
    pre[fy]=fx;
}
int main()
{
    int n_case;
    scanf("%d",&n_case);
    while(n_case--)
    {
        int people,contect,i;
        scanf("%d %d",&people,&contect);
        Init(people);
        for(i=1;i<=contect;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            jion(x,y);
        }
        int ans=0;
        for(i=1;i<=people;i++)
        {
            if(pre[i]==i) ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}


<think>好的,我需要处理用户关于并查集的问和练习的请求。首先,用户提到了并查集的基本概念,引用了站内的资料,所以我要确保回答中包含相关引用。接下来,用户想要练习和问,我需要生成一些典型的问,涵盖并查集的不同应用场景和操作。 首先,回顾并查集的基本操作:初始化、查找、合并和路径压缩。练习应该覆盖这些方面。例如,基础可能包括判断连通性,中级可能涉及动态合并和统计集合数量,高级可能结合其他算法或数据结构,比如Kruskal算法或图论问。 然后,我需要考虑常见的应用场景,比如朋友圈问、岛屿数量、最小生成树等。这些可以作为练习的背景。同时,目可能需要处理二维数组或复杂数据结构,以增加难度。 接下来,确保每个问都有明确的目标,比如返回集合数量或判断是否连通。此外,目可能需要优化操作次数或分析时间复杂度,这有助于用户深入理解并查集的效率。 还要注意引用格式,每个引用需在相关段落末尾自然添加。例如,在解释并查集概念时,加上[^1]。 最后,检查生成的问是否覆盖了不同难度层次,是否涉及并查集的关键操作和应用,确保用户通过练习能巩固知识并提升应用能力。同时,保持回答结构清晰,分点列出问,方便用户逐步练习。</think>### 并查集(Union-Find)练习与问 #### 基础练习 1. **连通性判断** 给定一组节点和若干连接关系(如边列表),判断两个指定节点是否连通。 示例输入:`n=5, edges=[[0,1],[1,2],[3,4]], queries=[[0,2],[1,3]]` 要求输出:`[True, False]` 关键点:使用并查集合并所有边,再处理查询。 2. **集合数量统计** 初始化`n`个独立集合,通过合并操作后,返回最终集合的总数。 示例输入:`n=6, 合并操作:[[0,1],[1,2],[4,5]]` 输出:`3`(集合为{0,1,2}, {3}, {4,5}) 实现提示:合并后遍历所有节点统计根节点数量。 3. **朋友圈问** `n`个人中,若`M[i][j]=1`表示i和j是朋友(朋友关系具有传递性),求朋友圈总数。 示例输入:`M=[[1,1,0],[1,1,0],[0,0,1]]` 输出:`2` 思路:将每行视为节点的合并操作,最终统计根节点数。 --- #### 中级练习 4. **动态合并与查询** 设计并查集,支持动态合并和实时查询集合数量。 示例操作: - `union(1,2)` → 集合数减1 - `union(2,3)` → 集合数再减1 - `count()` → 返回剩余集合数 要求:所有操作时间复杂度接近$O(1)$(使用路径压缩和按秩合并)。 5. **带权并查集** 扩展并查集,支持查询两个节点间的相对关系。例如: - 已知`A=B+3`和`B=C+2`,推导`A`与`C`的关系(`A=C+5`)。 应用场景:等式方程求解(如LeetCode 990)。 --- #### 高级应用 6. **最小生成树(Kruskal算法)** 使用并查集实现Kruskal算法,从带权图中选择边,使得生成树总权重最小且无环。 关键步骤: - 按边权重排序 - 依次选择边,若两端点不在同一集合则合并,否则跳过(避免环)[^1]。 7. **二维网格连通性问** 给定`m×n`网格,部分格子被阻塞,求从左上角到右下角的连通路径是否存在。 变体:动态添加/移除阻塞,实时判断连通性(结合并查集的动态特性)。 --- #### 实战编程(LeetCode示例) 8. **岛屿数量(LeetCode 200)** 二维网格中,`1`表示陆地,`0`表示,计算岛屿数量。 并查集解法:遍历网格,将相邻陆地合并,最终统计集合数。 9. **最长连续序列(LeetCode 128)** 给定无序数组,求最长连续数字序列的长度。 优化思路:用哈希表记录数字是否存在,并通过并查集合并连续数字。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值