hdu3234 ExclusiveOR

题意:

题目将以这样的形式进行提供已知条件或者提问,

分析:首先可以想到的是可以用并查集来做。

题目的是x1^x2^x3^……式子的值,

那么首先就要考虑俩个问题了:

1):如何记录x[]元素之间的关系

2):怎样传递元素之间的关系

这里我们注意到异或运算的性质:

对于a,b,c有:a xor b == c 和 a xor c == b 和 b xor c == a 等价,a^a==0

因此:我们用r[]数组保存该元素与根节点异或运算的关系;

接下来,为了方便处理,我们定义一个虚点xn,r[xn]=0,这样,只要根节点为xn的元素,这对于的具体也是已知的,同时,r[]的值就是其具体的值;而且,有一个好处就是,当进行I p v 操作时,相当于合并Union(p,n,v);

在压缩路径过程中,用r[x]^=r[f[x]] 求出与根节点的关系;

在判断能否计算出式子的值时,我们发现,根节点不为xn的元素,该集合必须出现偶数个的元素,否则该式子的具体值无法计算;

接下来就是读入数据的问题,额,我的方法比较笨……

基本已经可以实现了,看代码吧:

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int f[20010],r[20010],n;
int map[20010];
int xp[20],ans;
void init()
{
	for(int i=0;i<=n;i++)
	{
		f[i]=i;
		r[i]=0;
	}
}
int find(int x)
{
	if(x==f[x])
		return x;
	int t=find(f[x]);
	r[x]^=r[f[x]];//根据x与父节点的关系求出x与根节点的关系
	f[x]=t;
	return f[x];
}
bool Union(int x,int y,int k)
{
	int a=find(x);
	int b=find(y);
	if(a==b)
	{
		if((r[x]^r[y])==k)
			return true;
		return false;
	}
	if(a==n)
		swap(a,b);
		f[a]=b;
		r[a]=r[x]^r[y]^k;
	return true;
}
bool query(int m)
{
	memset(map,0,sizeof(map));
	for(int i=0;i<m;i++)
	{
		map[find(xp[i])]++;
		ans^=r[xp[i]];
	}
	int flag=0;
	for(int i=0;i<m;i++)
	{
		int t=find(xp[i]);
		if(map[t]%2!=0 && t!=n)
		{flag=1;break;}
	}
	if(flag)
		return false;
	 return true;

}
int main()
{
	char s[2],c;
	int a,b,v,Q,cas=0;	
	while(scanf("%d %d",&n,&Q)==2 &&(n||Q))
	{
		init();
		printf("Case %d:\n",++cas);
	int fact=0,flag=0;
	while(Q--)
	{
		scanf("%s%d%d",s,&a,&b);
		if(s[0]=='I')
		{
			fact++;
			c=getchar();
			if(c==' ')
			{
				scanf("%d",&v);
				if(flag)continue;
				if(!Union(a,b,v))
				{
					printf("The first %d facts are conflicting.\n",fact);
					flag=1;
				}
			}
			else
				{
					if(flag)continue;
					if(!Union(a,n,b))
					{
					  printf("The first %d facts are conflicting.\n",fact);
					  flag=1;
				    }
			    }
		}
		else 
		{
		    xp[0]=b;
			for(int i=1;i<a;i++)
				scanf("%d",&xp[i]);//额,这里有点多此一举
			if(flag)continue;
			ans=0;
			if(query(a))
				printf("%d\n",ans);
			else printf("I don't know.\n");
		}
	 }
	printf("\n");
	}
	return 0;
}


原文地址:https://www.cnblogs.com/nanke/p/2220998.html