首页 > 其他分享 >并查集的学习及运用

并查集的学习及运用

时间:2024-07-11 18:28:22浏览次数:19  
标签:return int 查集 long 学习 祖先 vec 运用 find

1.定义

在看并查集之前,我们先来看一下并查集是什么:

并查集是一种用于管理元素所属集合的数据结构。

它也有很多用途:在无向图中找环、判断连个元素是不是一个集合等等,所以用起来也十分方便,代码也很短

2.模板

int find(int k){
	if(vec[k]==k)return k;//判断自己还有没有祖先
	else return vec[k]=find(vec[k]);//找自己的祖先+压缩路径
}
void d(){
	int fx=find(x);//找x的祖先
	int fy=find(y);//找y的祖先
	if(fx!=fy){
		vec[fx]=vec[fy];//合并
	}
	return;
}

这是一个较为常用的模板,也十分的简洁明了,不过在具体的题中有具体的写法,这道只需把模板扔进去即可。

3.运用

这道修改数组题你会发现不用并查集竟然可以拿很高的分数:

#include<bits/stdc++.h>
using namespace std;
int n,a;bool b[1000007];
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a);
		for(int j=0;b[a];j++){//如果被标记过了,就一直加
			a++;
		}
		b[a]=true;//标记
		printf("%d%c",a,' ');
	}
	return 0;
}

这么easy的代码90分!!!

简直太离谱了,那我们来看一下正解:

先看思路:

我们在找到一个数时,可以直接输出他的祖先,并设置他的祖先+1的祖先的点为新的祖先,意思就是合并他的祖先和他的祖先+1;

拿这一组样例举例:5         2 1 1 3 4

第一次,输出2,合并2,3

第二次,输出1,合并1,2

第三次,输出3,合并3,4

第四次,输出4,合并4,5

 第五次,输出5,合并5,6

代码:

#include<bits/stdc++.h>
using namespace std;
int n,x;
int vec[1000007];
int find(int k){
	if(vec[k]==k)return k;
	else return vec[k]=find(vec[k]);
}
int main() {
	cin>>n;
	for(int i=1;i<=1000007;i++){
		vec[i]=i;
	}
	for(int i=1;i<=n;i++){
		cin>>x;
		if(x==find(x)){
			cout<<x<<' ';
			vec[x]=x+1;
		}else{
			cout<<find(x)<<' ';
			vec[find(x)]=find(x)+1;
		}
	}
	return 0;
}

这道题如果没有标签其实很难辨认出它是并查集,所以我们要多多观察,仔细看题;

还有一道题叫奶酪,这道题有好几种做法,我分享两种:

并查集:

#include<bits/stdc++.h>
using namespace std;
int f[1001];
int find(int x){
    if (x!=f[x]) f[x]=find(f[x]);
    return f[x];
}
long long dis(long long x,long long y,long long z,long long x1,long long y1,long long z1){
    return (x-x1)*(x-x1)+(y-y1)*(y-y1)+(z-z1)*(z-z1);
}
long long x[100001],y[100001],z[100001];
int f1[100001],f2[100001];
int main(){
    int t;
    scanf("%d",&t);
    int n,h; 
    long long r;
    for (int i=1;i<=t;i++){
        scanf("%d%d%lld",&n,&h,&r);
        int tot1=0;
        int tot2=0;
        for (int j=1;j<=n;j++){
          f[j]=j;
         }
        for (int j=1;j<=n;j++){
            scanf("%lld%lld%lld",&x[j],&y[j],&z[j]);
            if (z[j]+r>=h){
                tot1++;
                f1[tot1]=j;
            }
            if (z[j]-r<=0){
                tot2++;
                f2[tot2]=j;
            }
            for (int k=1;k<=j;k++){
            	if ((x[j]-x[k])*(x[j]-x[k])+(y[j]-y[k])*(y[j]-y[k])>4*r*r) continue;
                if (dis(x[j],y[j],z[j],x[k],y[k],z[k])<=4*r*r){
                    int a1=find(j);
                    int a2=find(k);
                    if (a1!=a2) f[a1]=a2;
                }
            }
        }
        int s=0;
        for (int j=1;j<=tot1;j++){
            for (int k=1;k<=tot2;k++){
                if (find(f1[j])==find(f2[k])){
                    s=1; 
                    break;
                }
            }
            if (s==1) break;
        }
        if (s==1) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
    return 0;
} 

BFS:

#include<bits/stdc++.h>
using namespace std;
struct chees {
	long long x, y, z;
};
long long n, h, r, t, k, nk;
chees nl[1007];
bool f[1007], tr;
queue<long long>q;
int main() {
	cin >> t;
	for (int i = 1; i <= t; i++) {
		cin >> n >> h >> r;
		for (int j = 1; j <= n; j++) {
			cin >> nl[j].x >> nl[j].y >> nl[j].z;
		}
		for (int j = 1; j <= n; j++) {
			if (nl[j].z - r <= 0) {
				q.push(j);
				f[j] = true;
				tr = false;
				while (!q.empty()) {
					k = q.front();
					q.pop();
					if (nl[k].z + r >= h) {
						cout << "Yes" << endl;
						tr = true;
						break;
					}
					nk = 1;
					while (nk <= n) {
						if (!f[nk] && sqrt((nl[k].x - nl[nk].x) * (nl[k].x - nl[nk].x) * 1. + (nl[k].y - nl[nk].y) * (nl[k].y - nl[nk].y) * 1.0 + (nl[k].z - nl[nk].z) * (nl[k].z - nl[nk].z) * 1.0) <= 2 * r) {
							q.push(nk);
							f[nk] = true;
						}
						nk++;
					}
				}
				while (!q.empty()) {
					q.pop();
				}
				memset(f, false, sizeof f);
				if(tr){
					break;
				}
			}
		}
		if (!tr) {
			cout << "No" << endl;
		}
		tr=false;
	}
	return 0;
}

还有几道有趣的题目,值得尝试:合根植物村村通网络分析

这里还有其他算法:BFSDFS

4.点个赞再走吧

标签:return,int,查集,long,学习,祖先,vec,运用,find
From: https://blog.csdn.net/2401_86209567/article/details/140346077

相关文章

  • Halcon学习笔记——Day2
    十四、halcon运行方式1、单步运行F62、F2重置程序执行3、F5连续运行,遇到stop或者断点会停止十五、特征直方图1、横坐标表示特征的值,纵坐标表示连通域的个数十六、灰度直方图1、threshold、scale_image2、行坐标表示灰度值 3、纵坐标表示像素个数十七、通过工具栏......
  • 中国人最容易学会的老挝语,《老挝语翻译通》App:做你的东南亚语言学习伙伴!
    ......
  • 机器学习实验报告实验名称: CNN 图片分类任务源码及高分报告
    机器学习实验报告实验名称:CNN 图片分类任目录目录2任务描述3数据集简介3目标3实验要求3实验内容4图片数据的加载和预处理,熟悉 PyTorch 中对数据集的处理4</......
  • [Python基础] matplotlib绘图的深入浅出学习
    matplotlib 是Python中最常用的绘图库之一,它提供了丰富的绘图功能,非常适合数据可视化。下面我将从整体逻辑开始,逐步深入到具体的例子matplotlib绘图整体逻辑:1、创建图像对象: plt.figure()2、绘制数据:plt.plot()等函数绘制数据 3、设置坐标轴、标签、图表标题等;现在,......
  • 昇思学习打卡-11-SSD目标检测
    文章目录模型介绍模型的特点数据采样网络结构损失函数公式实现NMS训练过程模型介绍SSD是单阶段的目标检测算法,通过卷积神经网络进行特征提取,取不同的特征层进行检测输出,所以SSD是一种多尺度的检测方法。在需要检测的特征层,直接使用一个3×3卷积,进行通道的变换。SSD......
  • Linux系统基础学习
    系统目录结构目录结构登录系统之后输入ls命令查看系统目录系统常用的目录/bin存放着最常用的命令,包括用户和系统管理员都会使用的命令。/boot存放启动linux的核心文件,包括内核文件、引导文件、镜像文件/dev存放着Linux系统中所有的设备文件,如硬盘、CD-ROM等/home......
  • Python机器学习实战:推荐系统的原理与实现方法
    Python机器学习实战:推荐系统的原理与实现方法1.背景介绍1.1问题的由来在当今数字化时代,推荐系统已成为电子商务、媒体流媒体平台、社交媒体以及在线购物网站的核心组件之一。推荐系统旨在根据用户的历史行为、偏好以及社会关系等因素,为用户提供个性化的内容或商品建议,......
  • 学习笔记——二叉平衡树(BST)
    二叉平衡树(BST)BST是一种数据结构,用于快速查找数据。二叉平衡树有一个非常明显的特性:对于每一个节点\(u\),在其左边的数都比它小,在其右边待数都比它大。每个点都有一个权值cnt,用于存储这个数出现了几次。在二叉平衡树上的每一个操作的时间与其树高成正比,约为\(O(\logn)\)。......
  • 2024最新,李宏毅深度学习!绝对值得反复阅读!
    介绍    李宏毅老师是台湾大学的教授,他的《机器学习》(2021年春)视频课程是深度学习领域中文视频中的经典之一。李老师风趣幽默的授课风格深受学生喜爱,他以很多动漫相关的有趣例子来解释深度学习理论,让原本晦涩难懂的内容变得轻松易懂。这门课程内容涵盖了深度学习中必须......
  • Linux学习笔记(03)——C编程入门
    vim编辑器需要先安装:sudoapt-getinstallvim使用vimxxx.txt:打开文件一般模式(指令模式):默认模式编辑模式:一般按下“a”进入编辑,按下ESC键可退出编辑模式命令行模式(底行模式):先进入一般模式,后输入:/?任意一个进入保存退出:进入底行模式,下面会出现:可在:后输入x保......