题意
给出一些事实,有两种情况
或者
需要计算的值。如果根据已经的事实,可以计算出则输出结果,否则输出I don't know。在给出的事实中,有可能会有冲突。
思路
使用并查集,使用val(x)来表示x与其父结点的异或值。在使用路径压缩时,val(x)最终会变成x与其根节点的异或值。
对于这种情况,可以转成
,在做这种合并时,将Xn作为根结点
可以计算出结果的情况下,在根结点不是Xn时,需要根结点的引用次数为偶数个
#include <bits/stdc++.h>
using namespace std;
const int N = 20010;
int p[N];
int val[N];
int n;
int vis[N];
struct Info
{
string c;
int p, q, v;
vector<int> vec;
};
void fastio()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
void init()
{
for (int i = 0; i <= n; i++) {
p[i] = i;
val[i] = 0;
}
}
int find_set(int x)
{
if (p[x] == x) {
return x;
}
int pa = p[x];
p[x] = find_set(p[x]);
val[x] ^= val[pa];
return p[x];
}
int main()
{
fastio();
#ifndef ONLINE_JUDGE
ifstream fin("f:\\OJ\\uva_in.txt");
streambuf* back = cin.rdbuf(fin.rdbuf());
#endif
int q;
int testCase = 1;
while (cin >> n >> q) {
if (n == 0 && q == 0) {
break;
}
string line;
getline(cin, line);
vector<Info> infos;
for (int i = 0; i < q; i++) {
getline(cin, line);
stringstream ss(line);
Info info;
ss >> info.c;
if (info.c[0] == 'I') {
vector<int> v;
int tmp;
while (ss >> tmp) {
v.push_back(tmp);
}
if (v.size() == 2) {
info.p = v[0];
info.q = n;
info.v = v[1];
} else {
info.p = v[0];
info.q = v[1];
info.v = v[2];
}
} else {
int k;
ss >> k;
for (int i = 0; i < k; i++) {
int tmp;
ss >> tmp;
info.vec.push_back(tmp);
}
}
infos.push_back(info);
}
/*for (size_t i = 0; i < infos.size(); i++) {
cout << "c:" << infos[i].c << " p:" << infos[i].p << " q:" << infos[i].q << " v:" << infos[i].v << endl;
}*/
init();
cout << "Case " << testCase++ << ":" << endl;
int facts = 0;
for (size_t i = 0; i < infos.size(); i++) {
char ch = infos[i].c[0];
if (ch == 'I') {
facts++;
//cout << "p:" << infos[i].p << " q:" << infos[i].q << endl;
/*for (int i = 0; i <= n; i++) {
cout << p[i] << " ";
}
cout << endl;*/
int pa = find_set(infos[i].p);
int pb = find_set(infos[i].q);
//cout << "pa:" << pa << " pb:" << pb << endl;
if (pa == pb) {
if ((val[infos[i].p] ^ val[infos[i].q]) != infos[i].v) {
cout << "The first " << facts << " facts are conflicting." << endl;
break;
}
} else {
if (pa == n) swap(pa, pb);
p[pa] = pb;
val[pa] = val[infos[i].p] ^ val[infos[i].q] ^ infos[i].v;
}
} else {
memset(vis, 0, sizeof(vis));
int ans = 0;
for (size_t j = 0; j < infos[i].vec.size(); j++) {
int pa = find_set(infos[i].vec[j]);
ans ^= val[infos[i].vec[j]];
if (pa != n) {
vis[pa] ^= 1;
}
}
bool flag = true;
for (int i = 0; i < n; i++) {
if (vis[i]) {
flag = false;
break;
}
}
if (flag) {
cout << ans << endl;
} else {
cout << "I don't know." << endl;
}
}
}
cout << endl;
}
#ifndef ONLINE_JUDGE
cin.rdbuf(back);
#endif
return 0;
}