一篇文章带你通关并查集(持续更新中)

这篇文章的所有题目均来自于自行整理,代码均来自于自行梳理调试(思路可能比较暴力)。初衷在于整理练习思路,且起到督促自己学习的作用

本文分成将三个模块

1.普及组 (洛谷黄题)

2.提高组 (洛谷绿题)

3.省选组 (洛谷蓝题及以上)

一、普及

1.P3367 【模板】并查集

普通并查集(纯板子,不加解释)

传送门icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P3367

// Problem: 
//     P3367 【模板】并查集
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3367
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include<iostream>
using namespace std;
const int N=1e4+10;
int e[N];int find(int x){if(x!=e[x]) e[x]=find(e[x]);return e[x];//返回根节点
}void merge(int a,int b){int x=find(a);int y=find(b);//e[x]=y;连接到另外一个上,我看了看板子更加复杂,但是符合原理都能过这里前面加一个if(x!=y)会更好,若不然可能增加路径压缩的次数
}int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;++i) e[i]=i;while(m--){int a,b,c;cin>>a>>b>>c;if(a==1){merge(b,c);}else{int k1=find(b);int k2=find(c);if(k1==k2) cout<<"Y"<<endl;else cout<<"N"<<endl;}}return 0;
}

2.P1551 亲戚

传送门icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1551

一道算是应用场景的题目,可以拿来熟熟手

// Problem: 
//     P1551 亲戚
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1551
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include<iostream>
using namespace std;
const int N=5005;
int fa[N];int find(int x){if(x!=fa[x]) fa[x]=find(fa[x]);return fa[x];//返回根节点
}void merge(int a,int b){int x=find(a);int y=find(b);fa[x]=y;
}int main(){int n,m,p;cin>>n>>m>>p;for(int i=1;i<=n;++i) fa[i]=i;while(m--){int a,b;cin>>a>>b;merge(a,b);}while(p--){int a,b;cin>>a>>b;int x=find(a),y=find(b);if(x==y) cout<<"Yes"<<endl;else cout<<"No"<<endl;}return 0;
}

3.P1111 修复公路

传送门icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1111

五花八门的答案,结合了一点排序知识

本人用了结构体排序后全遍历,O(nm)的时间复杂度(1e8)擦边过了

// Problem: 
//     P1111 修复公路
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1111
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e3+10;
int fa[N];
struct node{int a,b,c;bool operator < (const node &p)const {return c<p.c;};//重载
}nodes[100005];int find(int x){if(x!=fa[x]) fa[x]=find(fa[x]);return fa[x];
}void merge(int x,int y){int a=find(x),b=find(y);if(a!=b) fa[a]=b;//还是这么写吧,时间更优一点
}int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;++i) fa[i]=i;for(int i=1;i<=m;++i){cin>>nodes[i].a>>nodes[i].b>>nodes[i].c;}sort(nodes+1,nodes+1+m);for(int i=1;i<=m;++i){merge(nodes[i].a,nodes[i].b);bool check=true;for(int i=2;i<=n;++i){if(find(i)!=find(i-1)){//这里注意合并完没有merge的fa是没有直接更新的,不能直接比较fa[i]check=false;break;}}if(check){cout<<nodes[i].c<<endl;return 0;}}cout<<-1<<endl;return 0;
}

这个地方有更优的方法O(m),遍历一遍,如果遇到根节点不同,连通块数量减一并合并,这样连通块数量等于1的时候,输出答案就好了(只需要操作n-1次)

4.P2814 家谱

传送门icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P2814

这道题我个人结合了map,调到吐血,越改越复杂,细节还是蛮多的(不熟练

#include<iostream>
#include<map>
using namespace std;
const int N=5e4+10;
int fa[N];
map<string,int> mp;//记录每个点的标记
map<int,string> mpp;//在最后返回根节点的字符串
int cnt;int find(int x){if(x!=fa[x]) fa[x]=find(fa[x]);return fa[x];
}void merge(int f,int a){int x=find(f),y=find(a);if(x!=y) fa[y]=x;
}int main(){string s;int now;while(cin>>s){string k=s.substr(1);if(s=="$") break;else if(s[0]=='#'){if(!mp[k]){mp[k]=++cnt;fa[cnt]=cnt;now=cnt;mpp[cnt]=k;}else now=mp[k]; }else if(s[0]=='+'){if(!mp[k]){mp[k]=++cnt;fa[cnt]=cnt;mpp[cnt]=k;}merge(now,mp[k]);}else{int t=find(mp[k]);
//这个地方WA了n发,因为最后步find,这里还保留的是上一次的father,要find一次才能更新cout<<k<<' '<<mpp[t]<<endl;}}	return 0;
}

除了我的代码外,这里奉上大佬的一个题解,一样的思路,但是代码简单,炉火纯青。

(我被板子局限了思路,确实没想到路径压缩可以直接压缩map)

5.P1536 村村通

传送门icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1536

这道题如果把前面的吃透了,想起本文第三题结尾大佬的一个办法,计算连通块数量,如果find查找的根节点不同,就连通块数量-1并合并,连通块开始初始化为n-1。

// Problem: 
//     P1536 村村通
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1536
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include<iostream>
using namespace std;
const int N=1005;
int fa[N];int find(int x){if(x!=fa[x]) fa[x]=find(fa[x]);return fa[x];
}void merge(int a,int b){int x=find(a),y=find(b);if(x!=y) fa[x]=y;
}int main(){int a,b;while(cin>>a){if(a==0) break;for(int i=1;i<=a;++i) fa[i]=i;cin>>b;int ans=a-1;while(b--){int x,y;cin>>x>>y;if(find(x)!=find(y)) ans--,merge(x,y);}if(ans>=0) cout<<ans<<endl;else cout<<0<<endl;}	return 0;
}

这种方法的初衷其实更适合实时在某一刻卡断一类的,就是说能知道各时刻连通块的数量,这道题其实暴力就可以解决掉(因为给的全部都要操作)

6.P3958 [NOIP2017 提高组] 奶酪

传送门icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P3958非常伤心,这道题卡了我两个钟,最终发现原因(h的范围是1e9,不能直接暴力,写假了)

其实就是一段算成一个点,合并集合,最后把上下两个面再维护一下,看看上下两个面在不在一个集合里,可以配合这篇:远古大神 食用~

// Problem: 
//     P3958 [NOIP2017 提高组] 奶酪
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3958
// Memory Limit: 250 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N=1003;
#define int long long
int fa[N];
int n,h,r;
struct node{int a,b,c;
}nodes[N];
bool check(node x,node y){int num=(x.a-y.a)*(x.a-y.a)+(x.b-y.b)*(x.b-y.b)+(x.c-y.c)*(x.c-y.c);if(num>(2*r*r*2)) return false;return true;
}
int find(int x){if(x!=fa[x]) fa[x]=find(fa[x]);return fa[x];
}
void merge(int a,int b){int x=find(a),y=find(b);if(x!=y) fa[y]=x;//高的往低处接
}
signed main(){int t;cin>>t;while(t--){cin>>n>>h>>r;for(int i=1;i<=n+2;++i) fa[i]=i;for(int i=1;i<=n;++i){cin>>nodes[i].a>>nodes[i].b>>nodes[i].c;}for(int i=1;i<=n;++i){for(int j=i+1;j<=n;++j){if(check(nodes[i],nodes[j])){merge(i,j);}}}for(int i=1;i<=n;++i){if(nodes[i].c-r<=0) merge(i,n+1);if(nodes[i].c+r>=h) merge(i,n+2);//看看能不能串起来}if(find(n+1)==find(n+2)) cout<<"Yes"<<endl;else cout<<"No"<<endl;}return 0;
}

二、提高

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/519491.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3+ts(day01:Vue3简介、初始化Vue3工程)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes 觉得有帮助的同学&#xff0c;可以点心心支持一下哈&#xff08;笔记是根据b站上学习的尚硅谷的前端视频【张天禹老师】&#xff0c;记录一下学习笔记&#xff0c;用于自己复盘&#xff0c;有需要学…

响应式编程五股票订阅系统实现

响应式编程五 使用StepVerifier测试响应式流StepVerifier要点 使用StepVerifier进行高级测试股票订阅系统数据库表 使用StepVerifier测试响应式流 出于测试目的&#xff0c;Reactor 提供了额外的 reactor-test 模块&#xff0c;该模块提供了 StepVerifier。StepVerifier 提供了…

简易网络聊天室:2024/3/7

思维导图 基于UDP的简易网络聊天室 服务器&#xff1a; #include <myhead.h>#define SER_PORT 8888struct msgTyp //存储消息的结构体 {char type; //消息类型char name[30]; //用户姓名char text[1024]; //消息正文 };//创建链表存储客户端信息 typedef stru…

JavaWeb04-Request,Response

目录 一、Request&#xff08;请求&#xff09; 1.作用 2.继承体系 3.获取请求数据 &#xff08;1&#xff09;请求行 &#xff08;2&#xff09;请求头 &#xff08;3&#xff09;请求体&#xff08;POST&#xff09; &#xff08;5&#xff09;Request通用方式获取请求…

外包干了一周,技术明显倒退。。。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;2019年我通过校招踏入了南京一家软件公司&#xff0c;开始了我的职业生涯。那时的我&#xff0c;满怀热血和憧憬&#xff0c;期待着在这个行业中闯出一片天地。然而&#xff0c;随着时间的推移&#xff0c;我发现自己逐渐陷入…

【中高级】Java求职技能清单(2024版)

一、Java基础扎实&#xff08;反射、集合、IO、NIO、多线程、设计模式、通信协议等基础技术&#xff09; &#xff08;一&#xff09;Java &#xff08;二&#xff09;网络IO &#xff08;三&#xff09;NIO模型 &#xff08;…

项目经理如何应对多系统对接的项目?

对于项目经理来说&#xff0c;处理系统对接&#xff08;API对接&#xff09;的需求是一项既复杂又关键的任务。这项任务涉及到确保不同的系统能够高效、安全地共享数据&#xff0c;从而实现流畅的业务流程和提高整体的系统性能。下面是一个详细的指南&#xff0c;旨在帮助产品经…

海格里斯HEGERLS助力服装业领域数智化转型 配备7000个托盘位 仓库容量增超110%

近年来&#xff0c;用工荒成为服装制造行业的一大痛点。对此&#xff0c;整个生产体系就要不断地向智能化、自动化生产设备进行转型&#xff0c;甚至在研发设计上都要面向自动化做一些新一代服装制造业的开发。 作为较早入局物流赛道的河北沃克&#xff0c;目前已构建起以AI赋能…

学习统一的Hyper - network用于多模态MR图像合成和缺失模态的肿瘤分割

Learning Unified Hyper-Network for Multi-Modal MR Image Synthesis and Tumor Segmentation With Missing Modalities Learning Unified Hyper-Network for Multi-Modal MR Image Synthesis and Tumor Segmentation With Missing Modalities背景贡献实验方法多模态合成方法超…

工业制氧机的使用与维护管理指南

工业制氧机是工业生产中不可或缺的重要设备&#xff0c;其高效稳定的供氧功能对于保障生产过程的顺利进行至关重要。为了确保工业制氧机能够持续高效地提供氧气&#xff0c;正确的使用方法和维护措施是必不可少的。 在使用工业制氧机时&#xff0c;我们首先要确保设备放置在通风…

Java定时调度:Timer类和TimerTask类

Java提供了多种方式来执行定时任务&#xff0c;其中使用Timer类和TimerTask类是一种简单而有效的方法。这篇教程将介绍如何使用Java的Timer类和TimerTask类来实现定时调度。 1. Timer类 Timer类用于安排指定的任务按指定的时间执行。它可以执行一次性任务&#xff0c;也可以按…

【C语言】linux内核napi_gro_receive和netif_napi_add

napi_gro_receive 一、注释 // napi_gro_receive是网络设备接口的一个函数&#xff0c;它被NAPI&#xff08;New API&#xff09;网络轮询机制使用&#xff0c;用于接收和处理接收到的数据包。 // 这个函数通过通用接收分组&#xff08;GRO&#xff0c;Generic Receive Offlo…