51nod - 1515 明辨是非

给n组操作,每组操作形式为x y p。

当p为1时,如果第x变量和第y个变量可以相等,则输出YES,并限制他们相等;否则输出NO,并忽略此次操作。

当p为0时,如果第x变量和第y个变量可以不相等,则输出YES,并限制他们不相等 ;否则输出NO,并忽略此次操作。

输入

输入一个数n表示操作的次数(n<=1*10^5)
接下来n行每行三个数x,y,p(x,y<=1*10^8,p=0 or 1)

输出

对于n行操作,分别输出n行YES或者NO

输入样例

3
1 2 1
1 3 1
2 3 0

输出样例

YES
YES
NO

思路:

由于输入数据数值太大,因此需要用map将每个输入值映射到从1开始的连续值。

对于互斥的情况,在每个值安排一个set结构来记录与之互斥的值。

对于相同的情况,用并查集进行合即可,合并时将互斥数量小的合并到互斥数量大的,并且拷贝原来的互斥值。

#include <cstdio>
#include <set>
#include <map>
using namespace std;

const int MAXN = 2e5 + 10;

int n, num = 1;
int fa[MAXN];
int x, y, p;
set<int> dif[MAXN];
map<int, int> table;

int find(int x)
{
	if (x != fa[x])
	{
		fa[x] = find(fa[x]);
	}

	return fa[x];
}

int main()
{
	scanf("%d", &n);
	int size = n << 1;
	for (int i = 1; i <= size; i++)
	{
		fa[i] = i;
	}

	while (n--)
	{
		scanf("%d%d%d", &x, &y, &p);
		map<int, int>::iterator it = table.find(x);
		if (it != table.end())
		{
			x = table[x];
		}
		else
		{
			table[x] = num;
			x = num;
			num++;
		}

		it = table.find(y);
		if (it != table.end())
		{
			y = table[y];
		}
		else
		{
			table[y] = num;
			y = num;
			num++;
		}

		x = find(x);
		y = find(y);

		if (p == 1)
		{
			set<int>::iterator it = dif[x].find(y);
			if (it != dif[x].end())
			{
				puts("NO");
			}
			else if (x == y)
			{
				puts("YES");
			}
			else
			{
				if (dif[x].size() > dif[y].size())
				{
					swap(x, y);
				}

				fa[x] = y;
				for (it = dif[x].begin(); it != dif[x].end(); it++)
				{
					dif[*it].insert(y);
					dif[y].insert(*it);
				}
				puts("YES");
			}
		}
		else
		{
			if (x == y)
			{
				puts("NO");
			}
			else
			{
				dif[x].insert(y);
				dif[y].insert(x);
				puts("YES");
			}
		}
	}

	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值