开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");
}
}