图 之 MST(最小生成树 — kruskal算法 )并查集实现
2015-12-26 17:41
661 查看
#并查集的优化:
(1) Find_Set(x)时,路径压缩寻找祖先时,我们一般采用递归查找,但是当元素很多亦或是整棵树变为一条链时,每次Find_Set(x)都是O(n)的复杂度。为了避免这种情况,我们需对路径进行压缩,即当我们经过”递推”找到祖先节点后,”回溯”的时候顺便将它的子孙节点都直接指向祖先,这样以后再次Find_Set(x)时复杂度就变成O(1)了,如下图所示。可见,路径压缩方便了以后的查找。
(2) Union(x,y)时,按秩合并,即合并的时候将元素少的集合合并到元素多的集合中,这样合并之后树的高度会相对较小。
【输入】:
11
A B 7
A D 5
B C 8
B D 9
B E 7
C E 5
D E 15
D F 6
E F 8
E G 9
F G 11
【输出】:
A - D : 5
C - E : 5
D - F : 6
A - B : 7
B - E : 7
E - G : 9
39
【代码】:
(1) Find_Set(x)时,路径压缩寻找祖先时,我们一般采用递归查找,但是当元素很多亦或是整棵树变为一条链时,每次Find_Set(x)都是O(n)的复杂度。为了避免这种情况,我们需对路径进行压缩,即当我们经过”递推”找到祖先节点后,”回溯”的时候顺便将它的子孙节点都直接指向祖先,这样以后再次Find_Set(x)时复杂度就变成O(1)了,如下图所示。可见,路径压缩方便了以后的查找。
(2) Union(x,y)时,按秩合并,即合并的时候将元素少的集合合并到元素多的集合中,这样合并之后树的高度会相对较小。
【输入】:
11
A B 7
A D 5
B C 8
B D 9
B E 7
C E 5
D E 15
D F 6
E F 8
E G 9
F G 11
【输出】:
A - D : 5
C - E : 5
D - F : 6
A - B : 7
B - E : 7
E - G : 9
39
【代码】:
#include<stdio.h> #include<iostream> #include<algorithm> using namespace std; #define max_num 100 /* * 表示图的边 */ typedef struct edge { int x,y; int w; } edge; edge e[max_num]; int n = 0; //定义并查集 的parent数组和rank数组(树的深度-1——严谨的说) int parent[max_num]; int rank[max_num]; //最小代价 int sum = 0; //cmp函数-> 将e数组按权值w排序,当w相同,按x的升序 bool cmp(edge a,edge b) { if(a.w != b.w) { return a.w<b.w; } else { return a.x<b.x; } } /* * 并查集 */ void makeSet(int x) { parent[x] = x; rank[x] = 0; } int findSet(int x) { if(x != parent[x]) { parent[x] = findSet(parent[x]); } return parent[x]; } void unionSet(int x, int y, int w) { sum += w; if(x == y) return; if(rank[x]>rank[y]) { parent[y] = x; } else { if(rank[x] == rank[y]) { rank[y]++; } parent[x] = y; } } //图的创建 void creatGraph() { int x, y; char chx, chy; cin>>n; for(int i = 0; i<n; i++) { cin>>chx>>chy>>e[i].w; // getchar(); e[i].x = chx - 'A'; e[i].y = chy - 'A'; makeSet(i); } } /* * kruskal algorithm * 1.按权值将边数组排序 * 2.按顺序加入到MST中,前提是不会产生回路 */ void kruskal() { int x,y; sort(e,e+n,cmp); /* for(int i = 0; i<n; i++) { cout<<e[i].w<<endl; } */ for(int i = 0; i<n; i++) { x = findSet(e[i].x); y = findSet(e[i].y); if(x != y) { printf("%c - %c : %d\n",e[i].x+'A', e[i].y+'A', e[i].w); unionSet(x, y, e[i].w); } } cout<<sum<<endl; } int main() { creatGraph(); kruskal(); return 0; }
相关文章推荐
- 23种设计模式(4)_创建型_建造者模式(Builder Pattern)
- UVA 10780 Again Prime? No Time. 分解质因子
- HDU4405 Aeroplane chess
- LeetCode 94:Binary Tree Inorder Traversal
- 【算法拾遗(java描述)】--- 插入排序(直接插入排序、希尔排序)
- 体验vSphere 6之1-安装VMware ESXi 6 RC版
- smvc配置属性编辑器:
- 线程同步,对象级别的锁和类级别的锁
- Mac pro中的快捷键+Xcode中的快捷键
- 工作记录8:iOS 传值问题总结(7种传值完美介绍)
- 黑马程序员--多线程基础知识
- .net发邮件类
- 【NCRE】---拼接SQL语句(Case....When语句)
- 71道经典Android面试题和答案--重要知识点都涉及到了
- MongoDB 分片集群搭建
- 【APUE】8、pthread_create函数,创建子线程
- 一次使用 Redis 优化查询性能的实践
- java web生成验证码
- input(file)点击选择图片后,图片附件名称在另一个input(text)出现的实现
- URL,data(网络下载,url编码,文件读写),NSFileManager(文件管理者,系统单例)