POJ-2492-A Bug's Life

POJ-2492-A Bug’s Life

传送门

本题带权并查集
先开始我以为这道题跟那个龙派和蛇派的题目差不多=-=
但是后来想想不大对劲。这个题目是问你有没有错误。那个题是查询是否是同一个帮派。不对劲

题目大意:总是把题目中的bug想成代码中的bug,我真是bug脑袋=-=
实验开头结论一种稀有虫子只会吸引异性。问实验数据会不会有错或者存在同性相吸的可能
给出实验数据。

带权并查集哈
r[i]表示i与父结点的性别情况
为0表示同性。1表示异性

在find()函数和mix()函数中有关键代码
find()函数处理部分:
当前处理结点x
当发现父结点不是自己本身时。我们路径压缩过程中把根节点直接对应到了当前结点的父结点。所以relation关系要被改变
x与新父结点(根结点)的关系改为:x与原父结点的关系(就是r[x])+x原父结点与其父结点的关系(其父结点是根结点,r[fa[x]])
mod 2;
式子:r[x] = (r[x] + r[fa[x]]) % 2;
这里说x原父结点的父结点为啥是根结点?路径压缩路径压缩!

举个实际例子:x与原父结点的关系是:x为女孩子,原父结点为男孩子,即r[x] = 1,相异;
原父结点与根结点的关系:原父结点是男孩子(上面)根结点为女孩子,r[fa[x]] = 1;相异
所以x和根结点都是女孩子。当前更新:r[x] = 1;

mix()函数处理:
当x的根结点xx和y的根结点yy不一样时。我们需要合并树
这里把yy合并到xx上;
所以r[yy]需要被改变

x与xx的关系:r[x]
y与yy的关系:r[y]
(再强调一遍。路径压缩直接把x的父结点直接改为根结点了)

举一个实例:
r[x] = 1;假设x为女孩子,那xx为男孩子
r[y] = 0:假设y为女孩子,那yy为男孩子
yy合并到xx上(xx是yy的父结点)
所以我们根据数据找下关系
当前r[yy]应该更新为0(根据r[x]和r[y]找关系)
一定要mod2
相加减1就可以达到目的啦~

所以式子:
r[yy] = (r[x] + r[y] - 1 + 2) % 2;
这里加上2是为了防止负数(比如r[x]和r[y]均为0的情况)

好啦~解释完啦
最后注意格式输出
每组数据的输出用\n

代码部分:

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 2e3 + 10;

int fa[N];
int r[N];
int n, d;
int cnt;
int flag;

void init()
{
	for (int i = 1; i <= n; i++)
	{
		fa[i] = i;
		r[i] = 0;
	}
}

int find(int x)
{
	if (x != fa[x])
	{
		int xx = find(fa[x]);
		r[x] = (r[x] + r[fa[x]]) % 2;
		fa[x] = xx;
	}
	return fa[x];
}

void mix(int x, int y)
{
	int xx = find(x);
	int yy = find(y);
	if (xx == yy)
	{
		if (r[x] == r[y])
		{
			flag = 1;
		}
		return ;
	}
	fa[yy] = xx;
	r[yy] = (r[x] + 1 - r[y] + 2) % 2;
}

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		flag = 0;
		scanf ("%d%d", &n, &d);
		init();
		for (int i = 1; i <= d; i++)
		{
			int x, y;
			scanf ("%d%d", &x, &y);
			if (!flag)
			{
				mix(x, y);
			}
		}
		cout << "Scenario #" << ++cnt << ":" << endl;
		if (flag)
		{
			cout << "Suspicious bugs found!\n\n";
		}
		else
		{
			cout << "No suspicious bugs found!\n\n";
		}
	}
	return 0;
}
发布了127 篇原创文章 · 获赞 3 · 访问量 3231

猜你喜欢

转载自blog.csdn.net/qq_44624316/article/details/105127663
今日推荐