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

分析:首先可以想到的是可以用并查集来做。
题目的是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;
}