
2 6 I 0 1 3 Q 1 0 Q 2 1 0 I 0 2 Q 1 1 Q 1 0 3 3 I 0 1 6 I 0 2 2 Q 2 1 2 2 4 I 0 1 7 Q 2 0 1 I 0 1 8 Q 2 0 1 0 0
Case 1: I don‘t know. 3 1 2 Case 2: 4 Case 3: 7 The first 2 facts are conflicting.
题意:
有n(n<=20000)个未知的整数X0,X1,X2Xn-1,有以下Q个(Q<=40000)操作:
I p v :告诉你Xp=v
I p q v :告诉你Xp ^ Xq=v
Q k p1 p2 … pk : 询问 Xp1 Xor Xp2 .. Xor Xpk, k不大于15。
如果当前的I跟之前的有冲突的话,跳出
思路:
并查集,每个节点记录与根节点的异或偏移量,一个集合内如果有一个知道值了的话,这个集合里面都能知道值,(可以标记根是否已经得到值,或者像网上大部分人的做法,虚拟出一个节点n,值为0,将I操作统一)查询时,如果一个未知集合出现了偶数个,那么可以得到其值,u^root^v^root=u^v,如果出现奇数次,那么不能得到。Merge的时候有个小坑,见代码。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#include<sstream>
#define maxn 20005
#define MAXN 100005
#define mod 100000000
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
using namespace std;
int n,m,ans,cnt,tot,flag;
int pre[maxn],px[maxn],val[maxn],vis[maxn];
vector<int>root,q[16];
char s[5],buff[100];
int Find(int x)
{
if(x==pre[x]) return x;
int r=pre[x];
pre[x]=Find(pre[x]);
px[x]=px[r]^px[x];
return pre[x];
}
bool Merge(int u,int v,int w)
{
int x=Find(u),y=Find(v);
if(x!=y)
{
if(vis[x]||vis[y])// 如果有集合知道值 必须以知道值集合的根为根
{
if(!vis[y]) swap(x,y);
}
pre[x]=y;
px[x]=w^px[u]^px[v];
}
else
{
if((px[u]^px[v])!=w) return false ;
}
return true ;
}
void update()
{
int u,v,w;
cnt++;
gets(buff);
stringstream si;
si.clear(); si.str(buff);
si>>u; si>>v;
if(si>>w)
{
u++,v++;
if(flag) return ;
if(!Merge(u,v,w))
{
flag=1;
printf("The first %d facts are conflicting.\n",cnt);
}
}
else
{
if(flag) return ;
u++;
int r=Find(u);
if(vis[r])
{
if(val[r]!=(v^px[u]))
{
flag=1;
printf("The first %d facts are conflicting.\n",cnt);
}
}
else
{
vis[r]=1;
val[r]=v^px[u];
}
}
}
void query()
{
int i,j,u,v,k,r,flg;
scanf("%d",&k);
root.clear();
for(i=0;i<k;i++) q[i].clear();
for(i=1; i<=k; i++)
{
scanf("%d",&u);
u++;
int r=Find(u);
flg=0;
for(j=0;j<root.size();j++)
{
if(r==root[j])
{
flg=1;
q[j].push_back(u);
break ;
}
}
if(!flg)
{
root.push_back(r);
q[root.size()-1].push_back(u);
}
}
if(flag) return ;
flg=0;
int res=0;
for(i=0;i<root.size();i++)
{
if(vis[root[i]])
{
for(j=0; j<q[i].size(); j++)
{
res^=(px[q[i][j]]^val[root[i]]);
}
}
else
{
if(q[i].size()%2==1)
{
flg=1;
break ;
}
else
{
for(j=0; j<q[i].size(); j+=2)
{
u=px[q[i][j]]^px[q[i][j+1]];
res^=u;
}
}
}
}
if(flg) printf("I don't know.\n");
else printf("%d\n",res);
}
int main()
{
int i,j,t,u,v,w,test=0;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0) break ;
for(i=1; i<=n; i++)
{
pre[i]=i;
px[i]=vis[i]=0;
}
flag=cnt=0;
printf("Case %d:\n",++test);
for(i=1; i<=m; i++)
{
scanf("%s",s);
if(s[0]=='I') update();
else query();
}
puts("");
}
return 0;
}
hdu 3234 Exclusive-OR (并查集+异或性质),布布扣,bubuko.com
hdu 3234 Exclusive-OR (并查集+异或性质)
原文:http://blog.csdn.net/tobewhatyouwanttobe/article/details/38521663