并查集
来源:互联网 发布:澳门大学 知乎 编辑:程序博客网 时间:2024/05/26 09:54
上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B,那么既可以通过它从房间A走到房间B,也可以通过它从房间B走到房间A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从5到达8。
整个文件以两个-1结尾。
6 8 5 3 5 2 6 45 6 0 08 1 7 3 6 2 8 9 7 57 4 7 8 7 6 0 03 8 6 8 6 45 3 5 6 5 2 0 0-1 -1
YesYesNo
这是一道并查集问题。有一点弯,不会的可以先找出畅通工程先做一下。
下面我就说一下思路
这道题的要求是只有一个根节点,并且没有回路,就是没有根节点相同的情况。
int pre[100010];int s[100010];int ans; //定义全局变量,int Find(int x) //查找函数{ int r=x; while(pre[r]!=r) r=pre[r]; int i=x,j; while(pre[i]!=r) { j=pre[i]; pre[i]=r; i=j; } return r;}bool mix(int x,int y) //并在一起的函数。{ int fx=Find(x); int fy=Find(y); if(fx!=fy) pre[fy]=fx; else ans=0;}int main(){ int n,m; while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=100010;i++) //这一步一定要放在(使用)mix 函数的前面,不然 s[i]=0,pre[i]=i; //会出错。 if(n==-1&&m==-1) break; if(n==0&&m==0) { printf("Yes\n"); continue; } int mi,ma;ans=1; mi=min(n,m),ma=max(n,m); mix(n,m); s[n]=1,s[m]=1; while(scanf("%d%d",&n,&m)&&(n||m)) { int x,y; x=min(n,m),y=max(n,m); if(x<mi)mi=x; if(y>ma)ma=y; mix(n,m); s[n]=1,s[m]=1; } if(!ans) printf("No\n"); //先进行判断一下,也可以不判断,在下面再进行判断。 else { int k,i; for(k=0,i=mi;i<=ma;i++) //k是判断根节点的个数 { if(s[i]&&pre[i]==i) k++; if(k>1) { ans=0; break; } } if(ans) printf("Yes\n"); else printf("No\n"); } }}
做题还是要多注意细节,如果不注意,几个小时就检查那一点错误,太可惜了。
一年后了,自己成长了很多,在一次做这道题感触颇多 ,自己考虑了节点,但是没有考虑到,分开的情况。失误啊,还是要理解,不能敲模板啊。。。。
代码:::::
#include<stdio.h>#include<algorithm>#include<string.h>#include<math.h>#include<queue>#include<math.h>#include<iostream>const int inf=0x3f3f3f3f;using namespace std;int pre[100005];int vis[100005];int flag;int Find(int x){ int r=x; while(pre[r]!=r) { r=pre[r]; } int i=x,j; while(i!=r) { j=pre[i]; pre[i]=r; i=j; } return r;}void join(int x,int y){ int fx=Find(x); int fy=Find(y); if(fx!=fy) pre[fx]=fy; else flag=1;}int main(){ int n,m; while(~scanf("%d%d",&n,&m)) { if(n==-1&&m==-1) break; if(n==0&&m==0) { printf("Yes\n"); continue; } for(int i=1;i<=100004;i++) { pre[i]=i; vis[i]=0; } int n1,m1;flag=0; join(n,m); vis[n]=1; vis[m]=1; while(scanf("%d%d",&n1,&m1)&&n1&&m1) { vis[n1]=1; vis[m1]=1; join(n1,m1); } int k=0; for(int i=1;i<=100004;i++) //完全可以暴力一下,le5不会超时。 if(vis[i]&&pre[i]==i) k++; if(k>1)flag=1; if(flag==1) printf("No\n"); else printf("Yes\n"); }}
0 0
- HDU3938 并查集 并查集
- 并查集(集并查)
- HDU1232 并查集<并>
- 并查集
- 数据结构-并查集
- 并查集
- 并查集!
- 并查集
- 并查集
- 并查集
- 并查集
- 并查集总结
- 并查集学习
- 并查集
- 并查集
- 并查集
- 所谓并查集
- 并查集
- 三种方式清除浮动
- 使用apt安装pip时无法打开锁文件的解决办法
- 快速出现品牌关键词在百度360下拉框中进行推广
- python入门学习教程之List(列表)
- 匈牙利算法-二分图的最大匹配
- 并查集
- 大神教你如何安装win7系统
- JavaScript 闭包
- PostgreSQL 与基友们的故事之 - Redis (无限缓存,实时标签...)
- App服务端架构变迁
- 如何搭建testlink工具管理测试用例等
- 循环处理目录
- 应用层之DNS域名系统
- 如何在VirtualBox虚拟机上安装win7系统