HOJ 1272 小希的迷宫(简单并查集)

这题有点坑,WA了我很久。

讲三点需要注意的:是否连通、是否成环、是否空树。空树的意思是存在数据0 0,对,只有两个0。但两个0是符合题目的意思的,应该输出Yes,这就有点坑了。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int NN = 100000 + 5;
typedef struct point
{
	int a;
	struct point *p;
}point;

point t[NN];
int b[NN];

point find(point *x)//找一个点所在集合的标记点
{
	if ((*x).p == NULL) return *x;//如果是根节点,则返回自己
	return(find((*x).p));
}

int mer(int a, int b)
{//把两个点所在集合合并,操作是把b的根节点变成a的根节点的子节点(根节点的父节点为空)
	t[find(&t[b]).a].p = &t[find(&t[a]).a];
	return 1;
}


int main()
{			
	int n0, m0, n, m, flag;
	while (cin >> n0 >> m0)
	{
		if (n0 == -1 && m0 == -1) break;
		if (n0 == 0 && m0 == 0)
		{//这里坑,空树的数据00也是符合条件的,要输出Yes
			cout << "Yes" << endl;
			continue;
		}
		memset(&t, 0, sizeof(t));
		memset(b, 0, sizeof(b));
		flag = 1;			
		t[n0].a = n0;
		t[m0].a = m0;
		t[m0].p = &t[n0];
		b[n0] = n0;
		b[m0] = m0;
		while (cin >> n >> m)
		{
			if (!n && !m) break;
			b[n] = n;
			b[m] = m;
			t[n].a = n;
			t[m].a = m;
			if (find(&t[n]).a == find(&t[m]).a)//判断输入的两个数据是否以经在同一个集合中(根节点是否相同)
			{
				flag = 0;
				while (cin >> n >> m) if (!n && !m) break;//判断到读取的两个数据是在同一个集合中,则需要把剩下的该组数据读取完毕,跳出循环
				break;
			}
			mer(n, m);//n和m不在同一个集合中,把n和m加到数据中
		}

		int bb = 0;
		if(flag) //flag初时为1,如果有成环数据,则flag已变成0,不需要再判断有多少个集合
			for (int i = 0; i < NN; i++)//进行检索判断是否只有一个根节点即是否只有一个集合
			{
				if (bb == 0 && b[i] != 0)
				{
					bb = find(&t[i]).a;
					continue;
				}
				if (b[i] && find(&t[i]).a != t[bb].a)//b[i]为0表示没有数据i,判断若有数据根节点不相同,直接结束判断
				{
					flag = 0;
					break;
				}
			}

		if (flag) cout << "Yes" << endl;
		else cout << "No" << endl;
	}
	return  0;
}

猜你喜欢

转载自blog.csdn.net/qq_44724908/article/details/104169402