【原创】并查集之扩展域与边带权
【前言】
- 在一张无向图中维护节点之间的连通性或子图之间的连通性(图论优化)
- 动态维护许多具有传递性的关系(基本特性)
- 利用路径压缩来统计每个节点到树根之间路径上的一些信息(边带权)
- 维护具有多重关系的集合(扩展域)
【并查集之概念】
【并查集的代码实现(c++)】
- 初始化
for(int i=1;i<=t;i++) fa[i]=i;
- Get操作
int get(int x) {if(fa[x]==x) return x;get(fa[x]); }
- Merge操作
void merge(int x,int y) {fa[x]=y; }
【路径压缩】
int get(int x) {if(fa[x]==x) return x;return fa[x]=get(fa[x]); }
【最小生成树之kruskal】
- 在一张无向图中维护节点之间的连通性或子图之间的连通性
- 定理:任意一颗最小生成树总是包含无向图中权值最小的边。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; struct rec{int x,y,z; }edge[500010]; int fa[100010],n,m,ans=0; bool operator<(rec a,rec b){return a.z<b.z; } int get(int x){if(x==fa[x]) return x;else return fa[x]=get(fa[x]); } int main() {cin>>n>>m;for(int i=1;i<=m;i++)scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z);sort(edge+1,edge+m+1);for(int i=1;i<=n;i++) fa[i]=i;for(int i=1;i<=m;i++){int x=get(edge[i].x),y=get(edge[i].y);if(x==y) continue;fa[x]=y;ans+=edge[i].z;}if(ans) cout<<ans<<endl;else cout<<'MST not found'<<endl;return 0; }
【边带权的并查集】
[NOI2002]银河英雄传说
- Mi,j :i和j是两个整数(1≤i,j≤30000),表示指令涉及的战舰编号。该指令是莱因哈特窃听到的杨威利发布的舰队调动指令,并且保证第i号战舰与第j号战舰不在同一列。
- Ci,j :i和j是两个整数(1≤i,j≤30000),表示指令涉及的战舰编号。该指令是莱因哈特发布的询问指令。
M 2 3
C 1 2
M 2 4
C 4 2
1
int get(int x) { if(fa[x]==x) return x; int root=get(fa[x]); d[x]+=d[fa[x]]; return fa[x]=root; }
void merge(int x,int y) {int nx=get(x),ny=get(y);fa[nx]=ny;d[nx]=size[ny];size[ny]+=size[nx]; }
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<cstring> #define N 30010 using namespace std; int d[N],fa[N],size[N]; int get(int x) {if(fa[x]==x) return x;int root=get(fa[x]);d[x]+=d[fa[x]];return fa[x]=root; } void merge(int x,int y) {int nx=get(x),ny=get(y);fa[nx]=ny;d[nx]=size[ny];size[ny]+=size[nx]; } int main() {int t;cin>>t;fill(size+1,size+N,1);fill(d+1,d+N,0);for(int i=1;i<=N;i++) fa[i]=i;while(t--){char c;int x,y;cin>>c>>x>>y;if(c=='M') merge(x,y); else{ int nx=get(x),ny=get(y);if(nx==ny)printf("%d\n",abs(d[x]-d[y])-1); else cout<<"-1"<<endl;}}return 0; }
【扩展域并查集】
P1525 关押罪犯
1 4 2534
2 3 3512
1 2 28351
1 3 6618
2 4 1805
3 4 12884
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> #define N 100010 using namespace std; struct p{int x,y,val; }a[N]; bool operator<(p a,p b){return a.val>b.val; } int head[N<<1],fa[N<<3],tot,n,m; int get(int x) {if(fa[x]==x) return x;return fa[x]=get(fa[x]); } void merge(int x,int y) {x=get(x),y=get(y);if(x!=y) fa[x]=y; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=2*n;i++) fa[i]=i;for(int i=1;i<=m;i++){scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].val);}sort(a+1,a+m+1);int ans=0;for(int i=1;i<=m;i++){int x_self=a[i].x,x_another=a[i].x+n;int y_self=a[i].y,y_another=a[i].y+n;if(get(x_self)==get(y_self)||get(x_another)==get(y_another)){ans=a[i].val;break;}merge(x_self,y_another);merge(x_another,y_self);}cout<<ans<<endl;return 0; }
P2024 [NOI2001]食物链
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
1 #include<cstdio> 2 #include<algorithm> 3 #include<queue> 4 #include<cstring> 5 #include<iostream> 6 #define N 50010 7 using namespace std; 8 struct node{ 9 int x,y,flag; 10 }g[N<<4]; 11 int n,k,fa[N<<4]; 12 int get(int x) 13 { 14 if(fa[x]==x) return x; 15 return fa[x]=get(fa[x]); 16 } 17 void merge(int x,int y) 18 { 19 x=get(x),y=get(y); 20 fa[x]=y; 21 } 22 int main() 23 { 24 //freopen("fuc.in","r",stdin); 25 //freopen("fuc.out","w",stdout); 26 int cnt=0; 27 scanf("%d%d",&n,&k); 28 for(int i=1;i<=n*3;i++) fa[i]=i; 29 for(int i=1;i<=k;i++) 30 scanf("%d%d%d",&g[i].flag,&g[i].x,&g[i].y); 31 for(int i=1;i<=k;i++){ 32 if(g[i].x>n||g[i].y>n){ 33 cnt++;continue; 34 } 35 int x_self=g[i].x,x_enemy=g[i].x+n,x_eat=g[i].x+n+n; 36 int y_self=g[i].y,y_enemy=g[i].y+n,y_eat=g[i].y+n+n; 37 if(g[i].flag==1){ 38 if(get(x_eat)==get(y_self)||get(x_self)==get(y_eat)){ 39 cnt++; 40 } 41 else{ 42 merge(x_self,y_self); 43 merge(x_eat,y_eat); 44 merge(x_enemy,y_enemy); 45 } 46 } 47 else{ 48 if(get(x_self)==get(y_self)||get(y_eat)==get(x_self)){ 49 cnt++; 50 } 51 else{ 52 merge(x_self,y_enemy); 53 merge(x_eat,y_self); 54 merge(x_enemy,y_eat); 55 } 56 } 57 } 58 cout<<cnt<<endl; 59 return 0; 60 }
转载于:https://www.cnblogs.com/DarkValkyrie/p/10987053.html
【原创】并查集之扩展域与边带权相关推荐
- 238. 银河英雄传说(并查集,扩展域)
238. 银河英雄传说 - AcWing题库 分析: 由于要求i,j战舰之间的距离,我们就应该想到拓展域 拓展域要实现: 能够计算第i艘战舰到第j艘战舰距离 我们可以用一个拓展域来存储战舰 ...
- [kuangbin带你飞]专题五 并查集 E - 食物链 (带权并查集)
E - 食物链 题目链接:https://vjudge.net/contest/66964#problem/E 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C ...
- 图论500题 ---- (枚举+并查集)求图上路径权值差值最小 HDU find the most comfortable road
题目链接 解题思路: 对于两个点的路径假设我们把边按照边权进行排序那么,再把边依次加入图中判断两点的联通性,那么这个边就是两个点联通的最小的最大值,但是最大的最小值怎么找? 因为我们是把边权按照从小到 ...
- 0x41.数据结构进阶 - 并查集
目录 一.路径压缩与按秩合并 1.AcWing 237. 程序自动分析(NOIP2015) 二.边带权并查集 1.AcWing 238. 银河英雄传说(边带权并查集模板) 2.AcWing 239. ...
- 蓝桥备赛第四周 同余+并查集
文章目录 0x33 同余 同余类+剩余系+费马小定理+欧拉定理及推论 最幸运的数字 题解 这次的代码很多东西:欧拉函数快速求解,gcd,快速乘,各种定理,建议当模板背 10LL 转换成长整型 快速乘+ ...
- 我知道并查集的可爱之处
请开始您的并查集之旅 迈入门槛 文字概念 故事配图辅助理解 浅尝辄止 畅通工程 程序自动分析 supermarket 慢慢深入 银河英雄传说 parity game 1.带权并查集 2.扩展域并查集 ...
- 算法竞赛进阶指南0x41 并查集
并查集(Disjoint-Set)是一种可以动态维护若干个不重叠的集合,并支持合并与查询的数据结构.详细地说,并查集包括如下两个基本操作: 1.Get:查询一个元素属于哪一个集合. 2.Merge:把 ...
- 蓝桥侦探[蓝桥杯]——种类并查集
⭐️引言⭐️ 针对蓝桥侦探这道题,博主用了检查环的方法和种类并查集来解.其中检查环是会超时的,因为数据集比较大,所以最优法还是种类并查集,下面依次介绍. ⭐️目录⭐️ ⚡️题述 ⚡️解法1--判断环: ...
- HDU 5606 tree 并查集
tree 把每条边权是1的边断开,发现每个点离他最近的点个数就是他所在的连通块大小. 开一个并查集,每次读到边权是0的边就合并.最后Ansi=size[findset(i)],size表示每个并 ...
最新文章
- 【Python自学】六个上手超强的学习工具,你值得有
- asp.net js函数弹出登录窗口_JS基础 | Cocos Creator 开发环境搭建
- 福利丨吴恩达机器学习新书免费领!
- CodeForces 940E
- 【渝粤教育】广东开放大学 行政管理 形成性考核 (35)
- [2017-08-31]如何使用ruby同步markdown博文到博客园
- Intel超线程技术 Hyper-Threading Technology (4) - 处理器资源与超线程(分区的资源/竞争共享的资源)
- 做{...}而(0) - 有什么好处? [重复]
- 手机型号大全_2020值得入手的三款手机。每个优秀,选择哪一个?励志故事名言视频...
- Java虚拟机面试总结
- 必须安装三星系列android系统智能手机usb驱动程序,三星安卓4.0怎么刷机 三星安卓4.0刷机教程...
- BI报表工具有哪些?
- 企业微信付款到零钱,全代码讲解,包含怎么加入商户证书
- 解决Adobe Acrobat XI pro 开启十几秒自动闪退
- 华为手机自带浏览器无法下载 iis 网站 apk 问题解决方案(和SSL有关)
- 学习C++该看什么书?
- 互联网晚报 | 12月8日 星期三 | 淘宝购物车上线“好友买单”功能;英超联赛正式入驻视频号;中国联通成立5G消息生态联盟...
- qemu搭建arm嵌入式linux开发环境
- uniapp开发微信小程序/h5完整流程,含vant/uview(h5适配vw)
- SpringBoot使用tkmapper