• 并查集略解


    并查集 是一种十分简单的数据结构,支持以下操作:

    1. 将两个集合合并;
    2. 查询两个元素是否属于同一个集合。

    初始状态下,每个元素各自为一个集合。

    下面我们尝试实现这个算法。

    我们有四个元素,初始状态下各自为一个集合。
    在这里插入图片描述
    现在我们合并1,2元素。不妨认为把2加入到1所属的集合中,我们连一条边。
    在这里插入图片描述
    下次我们访问2元素的时候,检索到2指向1,我们就能知道12属于同一个集合。注意到,我们指定一个元素作为一个集合的代表,这个代表不会有指向另一个元素的边。判断两个元素是否属于同一个集合的方法就是判断两个元素属于的集合的代表是否是同一个元素

    现在我们将3加入到1,2所属的集合中。同理,我们得到
    在这里插入图片描述
    下次我们访问3的时候,我们会先找到3指向的元素2,再找到2指向的元素1。因为不用支持分开集合的操作,所以为了防止每次都线性遍历一边这个“链”,我们可以合并链,让集合里的每个元素都直接指向这个集合的代表。
    在这里插入图片描述
    至此,我们就实现了并查集

    实现文章开头提出的两个操作。

    #include 
    #include 
    #include 
    
    const int MAXN=10010;
    
    int n, m;
    //元素指向的元素
    int fa[MAXN];
    int s1, s2, s3;
    
    int findfa (int x){
    	//找到了集合的代表元素
    	if (x==fa[x]) return x;
    	//继续向前寻找,并压缩路径
    	return fa[x]=findfa (fa[x]);
    }
    int main (){
    	scanf ("%d%d", &n, &m);
    	//初始状态下,每个元素各形成一个集合。因此,每个元素属于的集合的代表就是他自己
    	for (int i=1; i<=n; ++i)
    		fa[i]=i;
    	for (int i=1; i<=m; ++i){
    		scanf ("%d%d%d", &s1, &s2, &s3);
    		if (1==s1)
    			fa[findfa (s2)]=findfa (s3);
    		else
    			puts ((findfa (s2)==findfa (s3))?"Y":"N");
    	} 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    习题1 luogu P1955 [NOI2015] 程序自动分析

    给出关于 x 1 , x 2 , . . . x_1,x_2,... x1,x2,... 的多个命题,每个命题为 x i = = x j x_i==x_j xi==xj x i ! = x j x_i!=x_j xi!=xj。问是否存在一组 x 1 , x 2 , . . . x_1,x_2,... x1,x2,...,使得所有命题都成立。

    本题的关键在于判断不等命题是否成立。不等条件较难判断,不妨先使得相等命题尽量成立,然后再判断不等命题是否成立。

    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    const int MAXN=1000010;
    
    int T, n;
    
    inline int read (){
    	int x=0; char c;
    	do c=getchar (); while ('0'>c||'9'=c)
    		x=x*10+c-48, c=getchar ();
    	return x;
    }
    struct oper{
    	int i, j, t;
    	oper(){
    		i=j=t=0;
    	}
    	void input (){
    		i=read (); j=read (); t=read ();
    	}
    }op[MAXN];
    //用于离散化的类,若1==id2则这个数来自op[id1].i,否则来自op[id1].j
    struct number{
    	int d, id1, id2;
    	number(){
    		d=id1=id2=0;
    	}
    }num[MAXN*2];
    int len;
    bool operator< (const number a, const number b){
    	return a.d
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    习题2 luogu P1621 集合

    给出正整数 l , r , s l,r,s l,r,s,求 [ l , r ] [l,r] [l,r] 中的集合个数,其中拥有不小于 s s s 的素公因子的数属于一个集合。

    回忆素数筛法过程,每次检索到一个素数后便把他的倍数全都设为合数。我们可以在这个过程中完成集合合并操作。

    #include 
    #include 
    #include 
    
    const int MAXN=100010;
    
    int l, r, st;
    int fa[MAXN];
    bool tf[MAXN];
    
    int findfa (int x){
    	if (fa[x]==x) return x;
    	return fa[x]=findfa (fa[x]);
    }
    int main (){
    	memset (tf, 1, sizeof (tf));
    	scanf ("%d%d%d", &l, &r, &st);
    	for (int i=1; i<=r; ++i)
    		fa[i]=i;
    	
    	for (int i=2; i<=r; ++i){
    		if (!tf[i]) continue;
    		for (int j=i; j<=r; j+=i)
    			tf[j]=0;
    		if (i
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
  • 相关阅读:
    【文末附gpt升级方案】人工智能在药物发现领域的革命性影响:以DeepMind的AlphaFold和Isomorphic Labs为例
    园子的商业化努力-困境求助:开设捐助通道
    【Linux】网络设置之基础操作命令详解
    ARM 汇编指令:(六) B 跳转指令
    Web大学生网页作业成品:基于html制作中国科技发展网站设计题材【航天之路7页】HTML+CSS+JavaScript
    外汇天眼;近年来“离岸监管”券商愈来愈多,这风潮为何让人又爱又恨?
    Roson的Qt之旅#100 QML四种标准对话框(颜色、字体、文件、提升)
    用 C实现 CRC-16/MODBUS x16+x15+x2+1校验计算
    【学习挑战赛】经典算法之直接插入排序
    Linux CentOS 8(HTTPS的配置与管理)
  • 原文地址:https://blog.csdn.net/YangHao5/article/details/126828914