[数据结构]第十章-并查集
来源:互联网 发布:nginx conf 配置php 编辑:程序博客网 时间:2024/06/02 05:03
并查集 : 以不相交集合为基础的抽象数据类型
· 支持运算:
1.UFunion(A,B,U):将并查集U中的集合A和B合并,其结果取名为A或B
2.UFfind(e):找出包含元素e的集合,并返回该集合的名字
· 实现思想:
每个集合用一棵树表示,树的结点用于存储集合中的元素名和一个指向其父节点的指针,树根结点的元素代表该树所表示的集合。
· 用父节点数组实现
数组 parent[x] 表示元素的父节点。
但在最坏情况下,n个结点的树可能退化为一条链。此时对所有元素各执行一次UFfind耗时O(n^2)。
改进方法:①按结点个数合并(结点少的合并到多的上,用parent[root] = -n记录根为root的树的结点个数n);②按高度合并(高度低的合并到高的上,记录方式同上);③按压缩路径(O(n(α(n))),α(n) < 4)
下面是泡泡的并查集模板
struct UF { int fa[MAX_N]; void init() { for(int i = 1; i < MAX_N; i++) fa[i] = i;} int find(int a) { return fa[a] == a ? a : fa[a] = find(fa[a]);} void mix(int a,int b) { fa[find(a)] = find(b);} bool isSame(int a, int b) { return find(a) == find(b);} } uf;
//–作业题
12.4 山海经
(题目很复杂其实只是想问两节点间的差值,有些已经能判断有些还不能,也即集合间的关系为是否已经能判断差值,能互相判断差值的扔进同一集合。如果AB间差值还不能判断,则语句d A B则把AB集合合并下并且AB结点之间差值为d。如果已经能判断则运算下是否为d以判断真假。差值的算法为,记录下集合中每个结点到根节点的差值qua,那么同一集合中的两节点ab就能通过a-fa-b的路径得到,在合并集合的时候更新a集合根节点的fa为b并且fa的qua通过fa-a-b-fb更新,合并的时候只要更新根节点就好,在find中回溯一边更新其他节点的qua。)
#include<iostream> #include<cstdio> using namespace std; #define MAX 50000+7 int pre[MAX]; int qua[MAX];//与pre的犇势差 int m,n,k,i; int find(int x) { int t; if(x != pre[x]) { t = pre[x]; pre[x] = find(pre[x]); qua[x] = (qua[x] + qua[t])%m; //回溯更新quax } return pre[x]; } void mix(int a, int b,int d) { int fa = find(a); int fb = find(b); if(fa != fb) pre[fa] = fb; qua[fa]=(m-qua[a]+d+qua[b])%m; //fa-a-b-fb 更新quafa } int main() { scanf("%d%d%d",&m,&n,&k); for(i = 1; i <= n; i++) { pre[i] = i; qua[i] = 0; } int d,a,b; int ans = 0; for(i = 1; i <= k; i++) { scanf("%d%d%d",&d,&a,&b); if(a > n || b > n || d >= m ) { ans++; continue; } int fa = find(a); int fb = find(b); if(fa == fb) { if((qua[a]+m-qua[b])%m != d) //a-f-b ab犇势差不为d ans++; } else mix(a,b,d); } printf("%d\n",ans); return 0; }
12.2 直通车
(朋友的关系可传递,敌人的关系不可传递。所以用并查集记录朋友关系,用二维数组记录敌人关系即可。)
#include<iostream> #include<cstdio> using namespace std; #define MAX 100+7 int pre[MAX]; int mp[MAX][MAX]; int n,m,k,i,j; void init() { int i; for(i = 1; i <= n; i++) pre[i] = i; } int find(int x) { int r = x; while(r != pre[r]) r = pre[r]; int i = x,j; while(i != pre[i]) { j = pre[i]; pre[i] = r; i = j; } return r; } void mix(int a, int b) { int fa = find(a); int fb = find(b); if(fa != fb) pre[fa] = fb; } int main() { scanf("%d%d%d",&n,&m,&k); init(); int x,y,op; for(i = 1; i <= m; i++) { scanf("%d%d%d",&x,&y,&op); mp[x][y] = op; mp[y][x] = op; if(op == 1) mix(x,y); } for(i = 1; i <= k; i++) { scanf("%d%d",&x,&y); int fx = find(x); int fy = find(y); if(fx == fy && mp[x][y] != -1) printf("Good job\n"); else if(fx != fy && mp[x][y] != -1) printf("No problem\n"); else if(mp[x][y] == -1) { if(fx == fy) printf("OK but...\n"); else printf("No way\n"); } } return 0; }
- [数据结构]第十章-并查集
- 数据结构-并查集
- 数据结构-并查集
- 并查集【数据结构】
- 【数据结构】并查集
- 数据结构-并查集
- 数据结构 并查集
- 数据结构 并查集
- 数据结构 -- 并查集
- 数据结构---并查集
- 数据结构---并查集
- 数据结构-并查集
- 数据结构 并查集
- 数据结构-并查集
- [数据结构].并查集
- 并查集 数据结构
- 数据结构-并查集
- 【数据结构】并查集
- using ffmpeg to convert ts to mp4 & split mp4 into multi segments
- android XML数据解析
- 剑指offer-----找出二叉搜索树第k个节点(java版)
- 欢迎使用CSDN-markdown编辑器
- Android -- IPC通信机制之一Binder简介
- [数据结构]第十章-并查集
- 51nod 1082 与7无关的数
- Android 自定义数字键盘(三)自定义输入框
- Mac OS下命令行终端无法输入中文或中文显示?
- ButterKnife:8.1.0的使用
- 排序算法总结
- Majority Element
- Redis+Mysql模式和内存+硬盘模式的异同
- git上传代码到github上