ntoj 1046 [NSCFXI]世界树

题目描述

世界的基本规律就是“负负得正”,也就是说,这个世界是到处在进行异或(XOR)运算的世界。现在有 N 个非负整数,并且它们的值不会发生变化。但是你并不知道它们究竟是那些数字。我们会给你一些事实,同时给出一些询问需要你进行处理。
有两种事实和一种询问:
I p v——表明第 p 个数的值是 v。
I p q v——表明第 p 个数和第 q 个数的异或值是 v。
Q k p1 p2 p3 … pk——求第 p1, p2, p3, … pk 个数的异或值。
注意,这 N 个数是从 0 开始编号的。

输入

输入文件包含多组测试数据。
每组测试数据的第一行包括两个整数 N, Q,分别表示数的个数和操作的数目。
之后 Q 行,每行一个如题目描述中所述的操作。
输入文件的最后一行包含两个 0,表示输入文件的终止。

输出

对于每个测试数据,在第一行输出“Case k:”,其中 k 表示测试数据的编号。
测试数据从 1 开始编号。
对于第 i 个事实(不计数询问),如果它与前面的事实有冲突,输出“The first i facts are conflicting.”,并且在这个测试数据中不要再输出任何内容。
对于每个询问,如果还没有出现冲突的事实,输出询问的结果。如果询问的结果不能被确定,输出“I don't know.”。
在每个测试数据的输出结束之后额外输出一个空行。

提示

测试数据保证最多 10 组。
对于所有的数据满足 1≤N≤20000,1≤Q≤40000。询问中的 k≤15,事实中的 v≤220。
保证有部分小数据。

类似于ural 1003

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5 + 10;
 4 
 5 int fa[N], dis[N], n, q, a[20], T = N - 1, vis[N];
 6 
 7 char inp[N];
 8 
 9 int get(int x) {
10     if(fa[x] == x) return x;
11     int f = get(fa[x]);
12     dis[x] ^= dis[fa[x]];
13     return fa[x] = f;
14 }
15 
16 int merge(int x, int y, int v) {
17     int fx = get(x), fy = get(y);
18     if(fx == fy) return (dis[x] ^ dis[y]) == v;
19     if(fx == T) swap(fx, fy);
20     fa[fx] = fy;
21     dis[fx] = dis[x] ^ dis[y] ^ v;
22     return 1;
23 }
24 
25 void sol() {
26     bool flag = 0;
27     for(int i = 0 ; i <= n ; ++ i) fa[i] = i, dis[i] = 0;
28     fa[T] = T, dis[T] = 0;
29     for(int i = 1, factot = 0 ; i <= q ; ++ i) {
30         char op[10]; scanf("%s", op);
31         if(op[0] == 'I') {
32             ++ factot;
33             gets(inp);
34             int p, q, v;
35             if(sscanf(inp, "%d%d%d", &p, &q, &v) == 2) v = q, q = T;
36             if(flag) continue;
37             if(!merge(p, q, v)) flag = 1, printf("The first %d facts are conflicting.\n", factot);
38         } else {
39             int k; scanf("%d", &k);
40             for(int j = 1 ; j <= k ; ++ j) scanf("%d", &a[j]);
41 
42             if(flag) continue;
43             int check = 1, ans = 0;
44             for(int j = 1 ; j <= k ; ++ j) {
45                 int x = a[j];
46                 a[j] = get(x);
47                 vis[a[j]] ^= 1;
48                 ans ^= dis[x];
49             }
50             for(int j = 1 ; j <= k ; ++ j) {
51                 if(vis[a[j]] && a[j] != T) {
52                     check = 0;
53                 }
54                 vis[a[j]] = 0;
55             }
56             if(check) printf("%d\n", ans);
57             else puts("I don't know.");
58         }
59     }
60 }
61 
62 int main() {
63     int T = 0;
64     while(scanf("%d%d", &n, &q) && !(!n && !q)) {
65         printf("Case %d:\n", ++ T);
66         sol();
67         puts("");
68     }
69 }
ntoj 1046 [NSCFXI]世界树
posted @ 2018-09-02 17:08  KingSann  阅读(170)  评论(0编辑  收藏  举报