標籤:des style blog http os width
Description
You are not given n non-negative integersX0,X1,...,Xn-1 less than220, but they do exist, and their values never change.
I‘ll gradually provide you some facts about them, and ask you some questions.
There are two kinds of facts, plus one kind of question:
| Format |
Meaning |
| I p v |
I tell you Xp = v |
| I p q v |
I tell you Xp XOR Xq = v |
| Q k p1 p2...pk |
Please tell me the value of Xp1 XOR Xp2 XOR...XOR Xpk |
Input
There will be at most 10 test cases. Each case begins with two integers n and Q (1n20, 000, 2Q40, 000). Each of the following lines contains either a fact or a question, formatted as stated above. Thek parameter in the questions will be a positive integer not greater than 15, and thev parameter in the facts will be a non-negative integer less than220. The last case is followed byn =Q = 0, which should not be processed.
Output
For each test case, print the case number on its own line, then the answers, one on each one. If you can‘t deduce the answer for a particular question, from the facts I provide youbefore that question, print ``I don‘t know.", without quotes. If thei-th fact (don‘t count questions)cannot be consistent withall the facts before that, print ``The firsti facts are conflicting.", then keep silence for everything after that (including facts and questions). Print a blank line after the output of each test case.
Sample Input
2 6 I 0 1 3Q 1 0 Q 2 1 0I 0 2 Q 1 1 Q 1 0 3 3 I 0 1 6I 0 2 2Q 2 1 22 4 I 0 1 7Q 2 0 1I 0 1 8Q 2 0 10 0
Sample Output
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,X2...Xn-1,有以下Q個(Q<=40000)操作:
I p v :告訴你Xp=v
I p q v :告訴你Xp Xor Xq=v
Q k p1 p2 … pk : 詢問 Xp1 Xor Xp2 .. Xor Xpk, k不大於15。
如果當前的I跟之前的有衝突的話,跳出
思路:並查集題目,深深的感到沒好好做並查集的無力感,知道是並查集卻不知道怎麼下手,說一下思路:
1.對於每次的詢問,我們並不需要知道每個數的大小也可以推出來結果,對於這種: I p v
的我們可以虛擬一個數xn=0,這樣就可以有通式p^q=v,因為p^0=p。虛根xn是不能變的,它的子孫都有確定的值
2.我們假設位移量val[i]=x[i]^x[fa[i]],還有熟悉a^b = 1 , b^c = 2 , 那麼 a^c = 1^2 = 3,還有異或可以互相轉化:a^b=c -> a^b^b=c^b -> a = b^c
3.為什麼會用到並查集呢,因為對於同一個集合裡的話我們可以通過他們與根的位移量和根的值來知道兩個數的異或結果,這樣更方便計算,同時計算:Q k x1 .. xk 的時候,就可以轉化為:(val[x1]^val[x2]..val[xk])^(x[fa[x1]]^x[fa[x2]]..x[fa[xk]]),然後利用異或偶數次不變的原理判斷必須是奇數次才有可以得到結果,判斷是不是xn根就是了
#include <iostream>#include <cstdio>#include <cstring>#include <map>#include <algorithm>using namespace std;const int MAXN = 20010;int n, m;int val[MAXN], fa[MAXN];int find(int x) {if (x != fa[x]) {int tmp = fa[x];fa[x] = find(fa[x]);val[x] ^= val[tmp];}return fa[x];}int Union(int x, int y, int v) {int fx = find(x);int fy = find(y);if (fx == fy)return (val[x]^val[y]) == v;if (fx == n)swap(fx, fy);fa[fx] = fy;val[fx] = val[x]^v^val[y];return 1;}int main() {char str[MAXN];int p, q, v, k, x;int cas = 1;while (scanf("%d%d", &n, &m) != EOF && n+m) {for (int i = 0; i <= n; i++) {val[i] = 0;fa[i] = i;}printf("Case %d:\n", cas++);int facts = 0;int err = 0;while (m--) {scanf("%s", str);if (str[0] == 'I') {gets(str);facts++;if (err)continue;int cnt = sscanf(str, "%d%d%d", &p, &q, &v);if (cnt == 2) {v = q;q = n;}if (!Union(p, q, v)) {err = true;printf("The first %d facts are conflicting.\n", facts++);}} else {scanf("%d", &k);int ans = 0;int is = 1;map<int, int> mp;for (int i = 0; i < k; i++) {scanf("%d", &x);if (err)continue;int f = find(x);ans ^= val[x];mp[f]++;}if (err)continue;map<int, int>::iterator it;for (it = mp.begin(); it != mp.end(); it++) {if (it->second % 2) {if (it->first != n) {is = 0;break;}else ans ^= val[it->first];}}if (is)printf("%d\n", ans);else printf("I don't know.\n");}}printf("\n");}return 0;}