并查集基础-----HDOJ1272-----小希的迷宫
2016-01-05 11:14
465 查看
[align=left]Problem Description[/align]
上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B,那么既可以通过它从房间A走到房间B,也可以通过它从房间B走到房间A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从5到达8。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201605/03/ce3d27d9f95d7ac87d47240232e2e0ba.jpg)
[align=left]Input[/align]
输入包含多组数据,每组数据是一个以0 0结尾的整数对列表,表示了一条通道连接的两个房间的编号。房间的编号至少为1,且不超过100000。每两组数据之间有一个空行。
整个文件以两个-1结尾。
[align=left]Output[/align]
对于输入的每一组数据,输出仅包括一行。如果该迷宫符合小希的思路,那么输出"Yes",否则输出"No"。
[align=left]Sample Input[/align]
[align=left]Sample Output[/align]
刚开始觉得很难,后来再写写发现也就那么回事
上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B,那么既可以通过它从房间A走到房间B,也可以通过它从房间B走到房间A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从5到达8。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201605/03/ce3d27d9f95d7ac87d47240232e2e0ba.jpg)
[align=left]Input[/align]
输入包含多组数据,每组数据是一个以0 0结尾的整数对列表,表示了一条通道连接的两个房间的编号。房间的编号至少为1,且不超过100000。每两组数据之间有一个空行。
整个文件以两个-1结尾。
[align=left]Output[/align]
对于输入的每一组数据,输出仅包括一行。如果该迷宫符合小希的思路,那么输出"Yes",否则输出"No"。
[align=left]Sample Input[/align]
6 8 5 3 5 2 6 4 5 6 0 0 8 1 7 3 6 2 8 9 7 5 7 4 7 8 7 6 0 0 3 8 6 8 6 4 5 3 5 6 5 2 0 0 -1 -1
[align=left]Sample Output[/align]
Yes Yes No
#include<cstdio> #include<cstring> int pre[100001], ok = 1, min, max, biaoji[100001]; int find(int x){ while(x != pre[x]){//查找根 x = pre[x]; } return x; } void merge(int x, int y){ int fx = find(x); int fy = find(y); if(fx != fy){ pre[fx] = fy; } else{//根节点相同,即在同一棵树,也就不符合题意,令判断符ok = 0,后续的点只输入不计算,降低时间复杂度 ok = 0; } } int main(){ int a, b; while(1){ for(int i = 1; i < 100001; i++){//初始化根节点 pre[i] = i; } min = 100000;//用两个变量表示输入数据的最大与最小值,缩小判断根节点的范围 max = 0; memset(biaoji, 0, sizeof(biaoji));//初始化标记点,使用过的标记为1,否则为0 scanf("%d%d", &a, &b); if(a == 0 && b == 0){//若第一对点就是0,0 直接输出Yes printf("Yes\n"); continue; } if(a == -1 && b == -1){ break; } while(a && b){ max = max > a ? max : a; max = max > b ? max : b; min = min < a ? min : a; min = min < b ? min : b; if(ok){ merge(a, b); } biaoji[a] = biaoji[b] = 1; scanf("%d%d", &a, &b); } int p = 0; for(int i = min; i <= max; i++){ if(pre[i] == i && biaoji[i]){//父节点是本身,即根节点,同时标记为1,即使用过,则计数器+ 1 p++; } } printf((ok && p == 1) ? "Yes\n" : "No\n"); ok = 1; } return 0; }
刚开始觉得很难,后来再写写发现也就那么回事
#include<cstdio> #include<algorithm> using namespace std; #define maxn 100005 int pre[maxn], vis[maxn]; int ok; int find(int a){ return a == pre[a] ? a : find(pre[a]); } void merge(int x, int y){ int fx = find(x), fy = find(y); if(fx != fy){ pre[fx] = fy; } else{ ok++; } } int main(){ int x, y, s, e, ans; for(int i = 0; i <= maxn; i++){ pre[i] = i; } ok = 0; s = 0; e = maxn; while(~scanf("%d%d", &x, &y)){ if(x == -1 && y == -1){ break; } if(x == 0 && y == 0){ ans = 0; for(int i = e; i <= s; i++){ if(i == pre[i] && vis[i]){ ans++; } if(ans > 1){ ok++; } pre[i] = i; vis[i] = 0; } printf(ok ? "No\n" : "Yes\n"); ok = 0; s = 0; e = maxn; continue; } merge(x, y); s = max(s, max(x, y)); e = min(e, min(x, y)); vis[x] = vis[y] = 1; } return 0; }
相关文章推荐
- Android夜间模式最佳实践
- 抓包工具 tcpdump
- java int与integer的区别
- Iperf是一个网络性能测试工具
- How can I protect derived classes from breaking when I change the internal parts of the base class?
- TIF转JPG
- OpenCV3.0 3.1版本的改进
- 拍死团队负能力
- JAVA Mysql中如何实现Blob的存取 -2
- iOS删除项目中未使用的图片资源
- WebAPI通过multipart/form-data方式同时上传文件以及数据(含HttpClient上传Demo)
- OpenCV3.0 3.1版本的改进
- webpack 试用
- 波特率误差分析
- MASTUDIO 移动办公客户应用集锦
- 关于原码、反码、补码详解
- Java程序的工具
- 15分钟学会使用Git和远程代码库
- 文件的存储读写,XML文件的存储与读写
- 关于使用MyEclipse自动生成Hibernate和Struts出现的jar不兼容的问题(antlr.collections.AST.getLine()I)