【树形数据结构】并查集

并查集并查集也是用来维护集合的,和前面学习的 set 不同之处在于,并查集能很方便地同时维护很多集 合。如果用 set 来维护会非常的麻烦。并查集的核心思想是记录每个结点的父亲结点是哪个结点。然而可以知道,这样空间时间复杂度极高,无法通过题目的时限.并查集基本基本结构初始化初始化很简单,将每个点所在集合初始化为它自己就可以了。void init() { for (int i = 1; i <= n; ++i) { fa[i] = i; }
摘要由CSDN通过智能技术生成

并查集

并查集也是用来维护集合的,和前面学习的 set 不同之处在于,并查集能很方便地同时维护很多集 合。如果用 set 来维护会非常的麻烦。并查集的核心思想是记录每个结点的父亲结点是哪个结点。然而可以知道,这样空间时间复杂度极高,无法通过题目的时限.

并查集基本

基本结构

  • 初始化
    初始化很简单,将每个点所在集合初始化为它自己就可以了。
void init() {    
 for (int i = 1; i <= n; ++i) {        
  	fa[i] = i;     
  } 
}
  • 查找
    这一步,我们只需要找到根节点,即元素所在的集合,然后继续判断。
int get(int x) {     
if (fa[x] == x) { 
// x 结点就是根结点         
return x;     
}   
return get(fa[x]); // 返回父结点的根结点 }
  • 合并
    将两个不同元素所在的集合合并为一个集合。
void merge(int x, int y) {     
x = get(x);     
y = get(y);    
 if (x != y) { // 不在同一个集合       
   fa[y] = x;     
 }
 }

实现并查集

首先,初始化

int fa[1000]; 
int n, m;

我们先把并查集的框架实现好,便于后面直接调用。初始化实际上就是把每个点的父亲结点赋值为自己。

void init() {    
	for (int i = 1; i <= n; i++) {         
 		fa[i] = i;     
	} 
} 

我们继续实现get函数

int get(int x) {     
	if (fa[x] == x) {         
		return x;     
	}     
	return get(fa[x]); 
}

接下里我们实现 merge 函数,合并两个结点到一个集合。

void merge(int x,int y) {    
	x=get(x);    
  	y=get(y);    
   	if (x!=y) {         
   		fa[y]=x;    
   } 
}

初始化要在 输入之后,这是平时写程序很容易错误的一个点。

cin >> n >> m;
init(); 
for (int i = 0; i < m; i++) {     
	int a, b;    
    cin >> a >> b;     
    merge(a, b); 
 }

最后我们统计几何的个数。

int cnt = 0; 
for (int i = 1; i <= n; i++) {    
	if (fa[i] == i) {        
		cnt++;    
   }
} 
 cout << cnt << endl; 

实现争取代码:

#include<bits/stdc++.h> 
using namespace std; 
int fa[10000];
int n,m; 
void init() {    
for (int i = 1; i <= n; i++) {        
    fa[i] = i;     
    } 
} 
int get(int x) {    
if (fa[x] == x) {        
    return x;    
}     
    return get(fa[x]); 
} 
void merge(int x, int y) {    
	x = get(x);     
    y = get(y);    
    if (x != y) {        
        fa[y] = x;     
    } 
} 
int main() {     
cin >> n >> m;     
init();     
for (int i = 0; i < m; i++) {        
	int a, b;         
	cin >> a >> b;        
	merge(a, b);     
}     
    int cnt = 0;    
    for (int i = 1; i <= n; i++) {         
        if (fa[i] == i) {             
                cnt++;         
        }    
    }     
    cout << cnt << endl;     
    return 0;
}

路径压缩

并查集的时间复杂度很高,最坏可以达到O(n),所以,我们更适用于路劲压缩的并查集,这一回,就来给大家讲一讲路劲压缩后的并查集。
路径压缩 的思想是,我们只关心每个结点所在集合的根结点,而并不太关心树的真正的结构是怎么样 的。这样我们在一次查询的时候,可以直接把查询路径上的所有结点的 都赋值成为根结点。实现 这一步只需要在我们之前的查询函数上面进行很小的改动。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值