51nod 1557 两个集合

开2倍n的并查集。其中,i所在的并查集与i+n所在的并查集,分别表示与数字p[i]所在的集合,以及数字p[i]所不在的集合。

也就是说,在正常情况下,i所在的并查集与i+n所在的并查集,不是同一个并查集。

利用map,对于每一个p[i],查找a-p[i]以及b-p[i]的元素下标i1和i2

根据查找情况,分别对i以及i+n进行并查操作。

若找到i1和i2,且都不为i,则代表,a-p[i]与b-p[i]必定不在同一集合内,则将i1与i2+n放在同一集合内,i1+n与i2放在同一集合内。

若只找到i1或i2,则代表i必定与i1或i2在同一集合内,则将i与i1或i2放在同一集合内,i+n与i1+n或i2+n放在同一集合内。

若找不到i1和i2,则答案为no。

最后,判断下i所在的并查集与i+n所在的并查集,不是同一个并查集是否成立,若不成立,答案也为no。

第一次没有考虑与i比较,WA 了两个点。。。

#include<bits/stdc++.h>
using namespace std;

const int MAXN=100100;
int fa[MAXN<<1],p[MAXN];
map<int,int> mp;

int findfa(int x)
{
	return fa[x]==x?x:fa[x]=findfa(fa[x]);
} 

int main()
{
	int n,a,b,i,flag,index1,index2;
	while(~scanf("%d%d%d",&n,&a,&b))
	{
		mp.clear();
		for(i=1;i<=2*n;i++)
			fa[i]=i;
		for(i=1;i<=n;i++)
		{
			scanf("%d",&p[i]);
			mp[p[i]]=i;
		}
		flag=1;
		for(i=1;i<=n;i++)
		{
			index1=mp[a-p[i]];
			index2=mp[b-p[i]];
			if(index1&&index2&&(index1!=index2)&&index1!=i&&index2!=i)
			{
				fa[findfa(index1)]=findfa(index2+n);
				fa[findfa(index2)]=findfa(index1+n);
			}
			else if(index1&&index1==index2)
			{
				fa[findfa(index1)]=findfa(i);
				fa[findfa(index1+n)]=findfa(i+n);
			}
			else if(index1&&!index2)
			{
				fa[findfa(index1)]=findfa(i);
				fa[findfa(index1+n)]=findfa(i+n);
			}
			else if(!index1&&index2)
			{
				fa[findfa(index2)]=findfa(i);
				fa[findfa(index2+n)]=findfa(i+n);
			}
			else if(!index1&&!index2)
				flag=0;
		}
		for(i=1;i<=n;i++)
		{
			if(findfa(i)==findfa(i+n))
				flag=0;
		}
		if(flag)
			printf("YES\n");
		else
			printf("NO\n");
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值