`
Simone_chou
  • 浏览: 192833 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

小希的迷宫(并查集)

    博客分类:
  • HDOJ
 
阅读更多

小希的迷宫

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 20149    Accepted Submission(s): 6170

Problem Description
上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B,那么既可以通过它从房间A走到房间B,也可以通过它从房间B走到房间A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从5到达8。
Input
输入包含多组数据,每组数据是一个以0 0结尾的整数对列表,表示了一条通道连接的两个房间的编号。房间的编号至少为1,且不超过100000。每两组数据之间有一个空行。
整个文件以两个-1结尾。
Output
对于输入的每一组数据,输出仅包括一行。如果该迷宫符合小希的思路,那么输出"Yes",否则输出"No"。
Sample Input
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
Sample Output
Yes
Yes
No
   思路:
   并查集。主要找有没有环,而且有没有超过一个以上的集合。

AC:

#include<stdio.h>
#include<string.h>
#define max 100000+5
int set[max];
int mark[max];

int find(int x)
{
	int r=x;
//初始化为set[i]=i
//所以根节点应该满足set[R]==R
//如果不满足条件则一层层往上找
//比如1到2到3,那么set[1]=2,set[2]=3,set[3]=3
	while(set[r]!=r)
	   r=set[r];
//循环体为r=set[r],说明到它的根节点处
//r表示的是此时处于的位置,set[r]是指r的根节点
	return r;
}

int main()
{
	int a,b;
	while(scanf("%d%d",&a,&b)!=EOF)
	{
		int x,y,temp=0,mi=max,ma=-1;
		memset(mark,0,sizeof(mark));
		for(int i=1;i<=max;i++)
		    set[i]=i;
//初始化
		if(a==-1&&b==-1) break;
		if(a==0&&b==0)
		{
			printf("Yes\n");
			continue;
		}
		if(a<mi) mi=a;
		if(b<mi) mi=b;
		if(a>ma) ma=a;
		if(b>ma) ma=b;
//这是为了找边界值
		set[a]=b;
		mark[a]=mark[b]=1;
//必须有mark标记数组,因为里面的节点不一定从1开始到N结束
//因为每次给出的交点值不一定是连续的
//所以每输入一个数就标记一个数
		while(scanf("%d%d",&x,&y)!=EOF&&x&&y)
		{
			int fx,fy;
			if(x>ma) ma=x;
			if(y>ma) ma=y;
			if(x<mi) mi=x;
			if(y<mi) mi=y;
			mark[x]=mark[y]=1;
			fx=find(x);
			fy=find(y);
			if(fx==fy)
			{
				temp=1;
				continue;
			}
			set[fy]=fx;
//将两个根节点连接,因为fy==set[fy],fx==set[fx]
//因为一开始初始化的时候以自身序号为集合代表
		}
		if(temp) printf("No\n");
		else
		{
//判断有没有可能出现一个以上的集合
			int sum=0;
			for(int i=mi;i<=ma;i++)
			  if(set[i]==i&&mark[i]) sum++;
//这时候mark数组标记就发挥用处了,0代表这个值没有出现过,1代表有出现过
//当set[i]==i时说明这个点为根节点,但是这个根节点必须曾经出现过
			if(sum==1) printf("Yes\n");
			else printf("No\n");
		}
	}
	return 0;
}

 为了更省时避免超时,这里的find函数可以改写:

int find(int x)
{
	int r=x,k;
	while(set[r]!=r)
	   r=set[r];
//路径压缩减少下次查询的时间
//如果处于结点的位置不是根节点的时候就循环
	while(x!=r)
	{
		k=set[x];
//先把x的根节点赋值给k
		set[x]=r;
//然后改变x的根节点,直接连到集合代表上
		x=k;
//改变完后,再改变x的根节点
//重复步骤,直到x==r,即直到到根节点本身则不需要改变路径了
	}
	return r;
}

   总结:

   一开始没路径压缩,但是也很神奇的通过了,某人说是因为数据太水了,所以还是用路径压缩写了一遍,也不难,用笔模拟一下也就什么都懂了。原来一开始理解有误,没有理解find函数为什么要那么循环来找根节点,理解了之后,也改进了之前的思路。这题还需要有个mark数组来标记有没有出现过的情况,因为给出的序号不一定是连续的,有两个情况不满足题目,就是有环和出现1个以上的集合。

分享到:
评论

相关推荐

    并查集生成迷宫及A*算法自动寻找路径

    并查集生成迷宫及A*算法自动寻找路径,学习算法的时候可以借鉴一下,很简单但是很实用。资源为整套源码。欢迎联系交流,共同学习。

    最小生成树+并查集题目列表.docx

    本资源提供了多种关于并查集的题目,例如 How Many Tables、小希的迷宫、Is It A Tree?等。 枚举最小生成树 枚举最小生成树是一种组合算法,用于解决最小生成树问题。本资源提供了多种关于枚举最小生成树的题目,...

    迷宫游戏(自动生成迷宫) 运用并查集自动生成迷宫地图,并运用队列和栈寻找迷宫通路并打印出来.zip

    在这个迷宫游戏项目中,我们主要探讨了两个关键算法:一是使用并查集(Disjoint Set)自动生成迷宫地图,二是通过队列和栈来寻找并打印出迷宫的通路。接下来,我们将深入讨论这两个核心概念及其在游戏开发中的应用。...

    并查集生成迷宫,并且利用AStar算法自动解迷宫

    并查集(Disjoint Set)是一种数据结构,用于处理一些不相交集合的合并与查询问题。在迷宫生成中,我们...理解并查集和AStar算法的原理以及它们在迷宫生成与解谜中的应用,对于提升算法设计和问题解决能力大有裨益。

    并查集(Union-Find)介绍.zip

    并查集是一种在计算机科学中用于管理集合的数据结构,它主要处理的问题是判断元素是否属于同一个集合,以及合并两个集合。这种数据结构在处理连通性问题时非常有用,例如在社交网络中查找用户是否相互认识,或者在...

    Qt随机迷宫及路径获取

    通过Qt的图形库创建迷宫界面,使用并查集管理迷宫中的连接关系,以及运用A*算法寻找最短路径,我们可以得到一个交互式的迷宫游戏或路径规划工具。这个项目不仅有助于提升编程技能,也是理解和应用数据结构与算法的好...

    迷宫 java 并查 union find

    利用数据结构中的并查集结构,根据输入的迷宫的行数和列数,自动生成迷宫。

    matlab迷宫

    2. 并查集迷宫生成:通过并查集连接随机的节点,构建迷宫结构。 3. DFS函数:实现递归的路径搜索。 4. 主程序:调用生成迷宫的函数,然后从起点开始执行DFS,输出或可视化路径。 通过这种方式,我们可以利用MATLAB...

    C++迷宫程序,文件读入,键盘控制走步

    通过逐行读取文件并解析成对应的迷宫格子状态,我们可以构建出迷宫地图。 2. **数据结构与算法**: 迷宫通常用二维数组表示,其中0代表可以通过的路径,1代表墙壁。解决迷宫问题可以使用深度优先搜索(DFS)、广度优先...

    C#实现4种经典迷宫生成算法和迷宫寻路算法

    在迷宫生成中,可以将迷宫的每个单元格看作一个集合,通过并查集维护它们的连通性。初始时,所有单元格都是独立集合,然后随机选择两个未连接的单元格进行连接,通过并查集的“联合”操作将它们合并为同一集合。不断...

    迷宫的生成与路由

    在生成迷宫时,可以将每个单元格看作一个节点,通过并查集来保持相邻单元格之间的连通性,确保生成的迷宫满足无环且联通的条件。在实际实现中,通常会使用路径压缩和按秩合并等优化策略来提高效率。 **搜索算法**是...

    随机迷宫的形成及迷宫路径查找与输出(不相交集的简单使用)

    功能介绍:根据不相交集原理随机生成迷宫并查找其路径,输出迷宫的数字及图文信息及带路径的图文信息(含文件操作) 设计时间:2010.3.20 测试平台:XP/VC++ 6.0及以上 BY 法官*/ 注:我写的这个是根据数据结构里的不相...

    迷宫游戏(自动生成迷宫)

    运用并查集自动生成迷宫地图,并运用队列和栈寻找迷宫通路并打印出来

    迷宫生成器1.0迷宫生成器1.0

    迷宫生成器1.0 迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫生成器1.0迷宫...

    迷宫生成与迷宫求解

    不相交集类算法是一种数据结构,用于高效地管理一组互不相交的集合,常用于解决并查集问题。通过随机选择并连接两个未连接的节点,可以生成一个无环图,即迷宫。这种方法能确保生成的迷宫具有唯一解,且具有良好的...

    C语言迷宫程序代码自动生成迷宫、自动输出路径

    本段C语言代码展示了如何实现一个自动生成迷宫并寻找从起点到终点最短路径的程序。通过随机生成迷宫、使用栈结构辅助深度优先搜索算法以及对路径进行有效的标记和显示,实现了迷宫问题的自动化解决。这种算法不仅...

    迷宫生成算法.rar

    本压缩包文件包含了几种经典的迷宫生成算法,分别是:并查集算法、深度优先搜索算法、随机算法和递归切割算法。接下来,我们将深入探讨这些算法。 首先,**并查集算法**是一种用于处理连接关系的数据结构,它可以...

    生成迷宫 - 深搜

    C/C++课程大作业,计算机系的同学都知道

Global site tag (gtag.js) - Google Analytics