UVALive 4487 Exclusive-OR
来源:互联网 发布:色系软件下载 编辑:程序博客网 时间:2024/05/04 22:15
#pragma warning(disable:4996)//UVALive 4487/*题意:每次告诉你两个变量的异或值,或者是一个变量的确切值,询问一些变量的异或值考点:并查集思路:每次告知信息时:将两个变量添加到并查集里(只给一个变量的确切值的时候看做是和一个数值为0的超级变量异或,因为x^0=x) 并且对于每个节点记录此节点与其祖先节点的异或值,做法就是从此结点一直更新到祖先节点,每个节点都异或上其直接父亲的值。 每次询问时:记录需要询问的变量的祖先节点的出现次数(超级变量不需要记录),只需要所有祖先出现的次数都是偶数既可以求出答案,否则don`t konw*/#include <stdio.h>#include <iostream>#include <algorithm>#include <vector>#include <string.h>using namespace std;#define maxn 20005int n;char tmp[105];vector<int>v;int p[maxn],pre[maxn],dp[maxn];int findpar(int x){ if(x != p[x]) { //这里的写法是关键,既要先获得x点以上所有父辈更新过的异或值,还要保证x点异或上其直接父亲的值。 int pp = p[x]; p[x] = findpar(p[x]); dp[x] ^= dp[pp]; } return p[x];}bool ok(){ if (v.empty())return 1; sort(v.begin(),v.end()); int pre = v[0],num = 1; for (unsigned i = 1;i<v.size();i++) { if(v[i] != pre) { if((num & 1) != 0)return 0; else num = 1,pre = v[i]; } else num++; } if((num & 1) == 0)return 1; else return 0;}bool merge(int x,int y,int res){ int c = findpar(x); int d = findpar(y); if(c != d) { if(c == n)swap(c,d),swap(x,y); p[c] = d; dp[c] = dp[x] ^ res ^ dp[y]; } else { if((dp[x] ^ dp[y]) != res) return 0; } return 1;}int main(){ int q,cas=0; while (cin>>n>>q && n+q) { printf("Case %d:\n",++cas); for (int i = 0;i<=n;i++) p[i] = i,pre[i] = i; memset(dp,0,sizeof dp); char s[5]; int err = 0,fact=0; for (int i=0;i<q;i++) { scanf("%s",s); int x,y,res; if(s[0] == 'I') { fact++; gets(tmp); if(err) continue; if(sscanf(tmp,"%d%d%d",&x,&y,&res)==2) { res = y; y = n; } if(!merge(x,y,res)) { err = 1; printf("The first %d facts are conflicting.\n",fact); } } else { int m,tmp; scanf("%d",&m); int ans = 0; v.clear(); for (int i = 0;i<m;i++) { scanf("%d",&tmp); if(err)continue; int pp = findpar(tmp); if(pp != n) v.push_back(pp); ans ^= dp[tmp]; } if(err)continue; if(ok()) printf("%d\n",ans); else puts("I don't know."); } } puts(""); } return 0;}
0 0