您的位置:首页 > 理论基础 > 数据结构算法

【并查集】数据结构与算法实验题 11.3 培养箱分配问题

2009-08-12 01:08 423 查看
数据结构与算法实验题 11.3 培养箱分配问题
★ 问题描述 :
生物学家 Finder 最近发现了一种有趣的虫子 BUG , BUG 有两种性别,当 相
同性别 的 BUG 生活在一起时,会发生剧烈的打斗,而当不同性别的 BUG 在一
起时,则 会 相处的非常好。
现在, Finder 找到了很多 BUG 虫,并将它们命名为 1 系列、 2 系列、 3 系
列 …… N 系列,每个系列的 BUG 虫之间是同性别的。 Finder 要将它们分配到培
养箱里培养,每个箱里两只。为了防止同性别之间的打斗,要求每个箱子里的
BUG 虫是不同性 别 的。
★ 实验任务:
现在 Finder 拟定了一个分配方案,但由于培养箱数量太多, Finder 也不能 确
定这种分配方案是否可行,即同一个培养箱中的 BUG 虫 会 不会打斗。现在, Fi nder
找到你,要你写一个程序验证他的分配方案是否可行。
★ 数据输入:
由 input.txt 给出输入。第一行有两个数 N , M ,表示 Finder 有 N 个系列的 BUG
虫,编号为 1 到 N , M 表示有 M 个培养箱,接下来 M 行每行两个数 A,B ,表 示
将 A 系列的 BUG 虫和 B 系列的 BUG 虫 放在 一起培养 (1<=A<=N,1<=B<=N) 。 注
意,输入数据有多组,必须处理到文件末尾。
★ 结果输出 :
输出到 ouput.txt 文件。每个方案输出一行,如果方案可行,输出 YES , 否
则输出 NO 。
★ 提示 :
多组数据 处理到文件末尾 的伪代码如下:
输入示例 
input.txt 
3 3
2 1
2 3
3 1
输出示例
output.txt
NO




本题可以使用路径压缩来加快速度,但是由于调试原因,所以没有加入。

不过要过ZOJ应该还是要使用路径压缩和 union小树到大树的。



我的思想是

例如这样一组数据

6 8
1 2
3 4
5 6
1 4
3 6
4 5
1 3

1 6
当出现1 2时候

我们把1和2各自归为一个集合,并且这两个集合是相对的。

当3 4时,因为还都是独立的元素,所以再各自归为一个集合,并且这两个集合是相对的。

当5 6时,因为还都是独立的元素,所以再各自归为一个集合,并且这两个集合是相对的。



当出现1 4时 因为 1 和4 都已经是集合的元素了,所以我们把那两个相对的集合合并。

也就是变成了(1 3)-(2 4)

当出现3 6时,因为 3 和6 都已经是集合的元素了,所以我们把那两个相对的集合合并。

也就是变成了(1 3 5 )-(2 4 6)

当出现4 5的时候,因为是出现在相对集合里面,所以不进行操作。

当出现1 3的时候,由于出现在同一个集合里面,所以不符合要求!可以输出no





#include <stdio.h>

int Find(int n, bool root[], int Set[])
{
	int i;
	i = n;
	while(1)
	{
		if (root[i] == true)
			return i;
		i = Set[i];
	}
}

int main()
{
	int m,n;
	int a,b;
	int flag;
	int i;
	int RootA,RootB;
	int Set[3000];
	bool root[3000];
	while (scanf("%d%d", &n, &m)!=EOF)
	{
		for(i=0;i<=n;i++)
		{
			Set[i] = i;
			root[i] = true;
		}
		flag = 0;
		for (i=0;i<m;i++)
		{
			scanf("%d%d", &a, &b);
			if (flag) continue;
			RootA = Find(a ,root, Set);
			RootB = Find(b,root, Set);
			if (RootA == RootB)
				flag = 1;
			else
			{
				if (Set[RootA]==RootA&&Set[RootB]==RootB)
				{
					root[RootA] = true;
					root[RootB] = true;
					Set[RootA] = RootB;
					Set[RootB] = RootA;
				}
				else if (Set[RootA]==RootA&&Set[RootB]!=RootB)
				{
					root[RootA] = false;
					root[RootB] = true;
					Set[RootA] = Set[RootB];
				} else if (Set[RootB]==RootB&&Set[RootA]!=RootA)
				{
					root[RootB] = false;
					root[RootA] = true;
					Set[RootB] = Set[RootA];
				} else if (Set[RootB]!=RootB&&Set[RootA]!=RootA)
				{
					root[RootA] = false;
					root[Set[RootA]] = false;
					root[RootB] = true;
					root[Set[RootB]] = true;
					//已经在两个相对集合里面了,就不要再改变了
					if (Set[RootA] != RootB)
					{
						Set[Set[RootA]] = RootB;
						Set[RootA] = Set[RootB];
					}
				}
			}
		}
		if (flag)
			printf("NO/n");
		else
			printf("YES/n");
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: