题解:HDU 1232: 畅通工程 (并查集)
来源:互联网 发布:网络拍卖许可证 编辑:程序博客网 时间:2024/05/17 07:38
上题目
Problem Description
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?Input 测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000
)和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通,也就是说 3 3 1 2 1 2 2 1 这种输入也是合法的 当N为0时,输入结束,该用例不被处理。Output 对每个测试用例,在1行里输出最少还需要建设的道路数目。
Sample Input
4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0
Sample Output
1
0
2
998
分析
基础的联通问题
看两个城市是否联通在一起
这里我们运用一种并查集的思想
我们设立一个标志节点 如果两个节点都可以上诉到同一个标志节点 那么这两个节点是联通的
这里用函数说明
全局变量部分
int father[1050];//father[i]所储存的数是father[i]的父节点的坐标int rank[1050]; // 表示这个数的在树中的深度
接下来是初始化的函数
我们先将每个数的父节点设置为他自己也就是每个数是独立的
将他的rank设置为0 代表深度为0; 函数
void init (int n){ for(int i = 0; i < n; i++) { father[i] = i; rank[i] = 0; }}
接下来是建立并查集的过程
这里本质上是合并两个集合的过程
比如 1和2联通 我们实际上就是合并1和2的最终父节点
注意这里在合并的过程中实际考虑了高度的问题
优先合并到较高的那一列
这样不会增加并查集的深度
void unite (int x, int y){ x = find(x); y = find(y); if(x == y) return; if(rank[x] < rank[y]) { father[x] = y;; } else { father[y] = x; if(rank[x] == rank[y]) rank[x]++; }}
接下来就是查找的查找的过程
可以这样理解
因为father[i]存储的是i的父节点 所以我们可以一直向上遍历
直到出现 father[i] = i 的情况
也就是他的父节点是他自己
这时他就是最终的父节点
这里先上递推版的
int find(int x){ int far = x; while (far != father[far])// 寻找最终父节点 far = father[far]; return far;}
路径压缩问题
这里我们的做法是将全部的子节点合并到最终父节点下
int minn(int x){ int far = find(x); int i = x; while (father[i] != far)// 状态压缩 将各级子节点压缩到最终父节点下 { int temp = father[i]; father[i] = far; i = temp; } return far;}
上代码+ 注释
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int father[1050];int t[1050];int find(int x){ int far = x; while (far != father[far])// 寻找最终父节点 far = father[far]; int i = x; while (father[i] != far)// 状态压缩 将各级子节点压缩到最终父节点下 { int temp = father[i]; father[i] = far; i = temp; } return far;}void mix(int x, int y){ int fx = find(x); int fy = find(y); if (fx != fy) { father[fy] = fx; }}int main(void){ int N, M, a, b, i, j, ans; while (scanf("%d%d", &N, &M) && N) { for (i = 1; i <= N; i++) //初始化 father[i] = i; for (i = 1; i <= M; i++) //吸收并整理数据 { scanf("%d%d", &a, &b); mix(a, b); } memset(t, 0, sizeof(t)); for (i = 1; i <= N; i++) //标记根结点 { t[find(i)] = 1; } for (ans = 0, i = 1; i <= N; i++) if (t[i]) ans++; printf("%d\n", ans - 1); } return 0;}
- 题解:HDU 1232: 畅通工程 (并查集)
- hdu 1232 畅通工程 并查集
- HDU 1232 畅通工程 并查集
- HDU 1232 畅通工程 (并查集)
- hdu 1232畅通工程 并查集
- hdu 1232 畅通工程 并查集
- HDU--1232--畅通工程--并查集
- 畅通工程-并查集-hdu 1232
- hdu 1232 畅通工程并查集
- HDU 1232 畅通工程 并查集
- hdu 1232 畅通工程 并查集
- hdu 1232 畅通工程(并查集)
- HDU 1232 畅通工程(并查集)
- HDU 1232 畅通工程(并查集)
- HDU 1232 畅通工程 并查集
- 并查集:hdu 1232 畅通工程
- HDU - 1232 畅通工程 <并查集>
- hdu 1232 畅通工程(并查集)
- 由“多说评论系统”想到的, Web后端的SOA化、及服务组合、与Web Components的结合?
- leetcode之移除指定元素(PHP)
- Apache+Tomcat+Terracotta+Ehcache负载均衡和分布式会话,缓存框架搭建
- 电子或通信领域当前的主流技术及其社会需求调查报告
- C/C++ Find the missing number
- 题解:HDU 1232: 畅通工程 (并查集)
- bc+2,3,5倍数看末尾和各位数和+毕竟这个数据为10^30
- 数据的存储方案
- 第一次写博客,关于AJAX的异步交互
- Android Studio 中Git使用教程
- 观《闻香识女人》有感
- pat 1007. Maximum Subsequence Sum (25)
- 使用HttpClient实现文件的下载
- bc+变化后与变化前相减成一个数组,然后就是求最大子串和的问题了