CSU 1045: 并查集(带权并查集)

本文介绍了一种使用带权并查集解决特定问题的方法。输入包含多组数据,每组由一组编号及其对应的关系组成,通过并查集算法找出组员最多的组,并输出其成员数量。

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

CSU 1045: 并查集 带权并查集

Description

大一的学一下,大二以上还不会并查集的统统去面壁。

Input

多组数据,每组第一行两个正整数n,m,表示有1~n这n个编号,m个关系。

接下来m行,每行两个数i, j, 1 <= i, j <= n,表示i和j是一组的。

每个编号自己和自己是一组的。

1 < n < 1000000 ,1 < m < 100000 。

Output

每组数据输出一行,一个数,表示组员最多的组的组员个数。

Sample Input

10 5
1 2
3 5
2 6
4 7
9 6

Sample Output

4

Hint

Source

中南大学2012年暑期集训队选拔赛

思路: 带权并查集

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int f[1000005];
int n,m;
int a,b;
int father(int x)
{
    if(f[x] <=0 )
        return x;
    else
        return f[x] = father(f[x]);
}
void union_(int a,int b)
{
    int root1 = father(a);
    int root2 = father(b);
    if(root1 == root2)
        return;
    f[root1] += f[root2];
    f[root2] = root1;
}
int main()
{
    while(scanf("%d%d",&n,&m) != EOF)
    {
        memset(f,-1,sizeof(f));
        for(int i = 0 ; i < m ; i++)
            scanf("%d%d",&a,&b),union_(a,b);
        int minx = 0;
        for(int i = 1 ; i <= n ; i++)
            minx = min(minx,f[i]);
        printf("%d\n",-minx);
    }
    return 0;
}
并查集(Union-Find)是一种用于处理一组不相交集合的合并与查询操作的树型数据结构。它支持两种主要操作:**合并**(Union)两个集合,以及**查找**(Find)某个元素所属的集合。这种数据结构在解决动态连通性问题时非常高效,尤其是在图算法和网络连接问题中。 ### 原理 并查集的核心思想是使用一棵树来表示一个集合,树中的每个节点代表一个元素。通常,树的根节点是该集合的代表元素。每个节点只需要记录其父节点,而根节点的父节点指向自己。查找一个元素所属集合时,需要沿着父节点指针一直向上查找,直到找到根节点为止。合并两个集合时,只需要将其中一个树的根节点连接到另一个树的根节点上。 为了提高效率,通常会使用两种优化策略: - **路径压缩**:在查找过程中,将查找路径上的所有节点直接连接到根节点,从而缩短树的高度,加快后续查找操作的速度。 - **按秩合并**:在合并两个集合时,总是将较小的树连接到较大的树上,这样可以避免树的高度增长过快,从而减少查找操作的时间复杂度。 ### 实现 并查集可以用数组或哈希表来实现。以下是一个简单的 Python 实现示例: ```python class UnionFind: def __init__(self, size): # 初始化父数组,每个元素的父节点初始化为自己 self.parent = list(range(size)) # 秩数组用于按秩合并 self.rank = [0] * size def find(self, x): # 查找x的根节点,路径压缩 if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): # 合并x和y所在的集合 rootX = self.find(x) rootY = self.find(y) if rootX == rootY: return # 已经在同一集合中 # 按秩合并 if self.rank[rootX] > self.rank[rootY]: self.parent[rootY] = rootX elif self.rank[rootX] < self.rank[rootY]: self.parent[rootX] = rootY else: self.parent[rootY] = rootX self.rank[rootX] += 1 ``` 在这个实现中,`find` 方法用于查找某个元素的根节点,并在查找过程中进行路径压缩。`union` 方法用于合并两个集合,并通过秩来决定如何合并,以保持树的低高度。 ### 应用场景 并查集广泛应用于以下场景: - **连通性问题**:例如,在图中判断两个顶点是否属于同一个连通分量,或者动态地维护图的连通性。 - **最小生成树算法**:Kruskal 算法使用并查集来检测图中的环,从而选择不形成环的边来构建最小生成树。 - **图像处理**:在图像分割中,可以使用并查集来识别和标记不同的连通区域。 - **社交网络分析**:在社交网络中,可以使用并查集来查找用户之间的关系网络,判断两个人是否属于同一个社交圈。 通过这些应用场景可以看出,并查集是一种非常实用的数据结构,尤其适合处理需要频繁进行合并和查找操作的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值