zoukankan      html  css  js  c++  java
  • C++ P3367 【模板】并查集

    本来打算尝试学一下LCA的,但是发现似乎离线算法需要预备知识:并查集,于是尝试学了一下并查集。

    并查集的思想:
    有时候我们需要对一个集合进行操作,比如判断某个数是否属于另一个数所属于的某个集合,那么我们就可以用这样的思想:
    每一个集合只存一个代表,集合中的其他元素都连接这个代表,而这个集合中除了代表连接着其他元素,其他元素不互相连接。
    这样的话,速度就快很多了。比如原来我们可能需要这样:
    对于一个集合大小为n的集合,时间复杂度为O(n)
    而使用并查集后,复杂度为O(1)
    代码:

    #include<cstdio>
    #include<iostream>
    using namespace std;
    int data[10001];
    int find(int k){
    	if(data[k]==k)return k;
    	return data[k]=find(data[k]);
    }
    int main(){
    	int n,m;
    	cin>>n>>m;
    	for(int i=1;i<=n;i++){//n个元素 
    		data[i]=i;
    	}
    	for(int i=0;i<m;i++){//m个操作 
    		int a,b,c;
    		cin>>a>>b>>c;
    		if(a==1){
    			data[find(data[b])]=find(c);//将b的爸爸变成c的爸爸  注意,这里需要让b的最大的爸爸的爸爸变成c的最大的爸爸。在find的同时就会更新每个元素的爸爸为当前的总爸爸(return时的处理) 
    		}else if(a==2){
    			if(find(b)==find(c)){
    				cout<<"Y"<<endl;
    			}else{
    				cout<<"N"<<endl;
    			}
    		}
    	}
    }
    

    关键的方法就是find(int k)方法。重点是对这个方法的理解,剩余的内容主要是输入的进行。对这个方法的理解可以看一下洛谷的题解。

    我对find(int k)方法的理解:
    第一行{ if(data[k]==k)return k; }:k的值为要查询的值,方法本身的用处是查找k的最大的父亲,那么这一行的意思就是:如果k的父亲是他自己,就返回他自己。
    第二行{ return data[k]=find(data[k]); }:如果k的父亲不是k自己,就查找 k的父亲 的最大的父亲,并设置k的最大的父亲为 k的父亲 的最大的父亲。这样就可以得出,从k到k次一级的父亲都会直接变成最大的父亲的儿子。

    题目(洛谷):https://www.luogu.org/problemnew/show/P3367
    题解(洛谷):https://www.luogu.org/problemnew/solution/P3367

  • 相关阅读:
    HDFS的工作流程分析
    linux文本分析利器awk
    二叉树遍历
    tomcat 工作原理简析
    徐汉彬:Web系统大规模并发——电商秒杀与抢购
    牛人博客 列表
    消息队列 概念 配合SpringBoot使用Demo
    Redis 实例排除步骤
    Java分布式 一些概念理解
    消息成功失败回调demo
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680732.html
Copyright © 2011-2022 走看看