首页 > 代码库 > UVA12232 - Exclusive-OR(带权并查集)
UVA12232 - Exclusive-OR(带权并查集)
题目:UVA12232 - Exclusive-OR(带权并查集)
题目大意:给你I P V 代表Xp 的值是V。或者 I P Q V 代表X P ^X i + 1 ^X i+2 ...^X^Q = V;然后给你Q k p1 p2 p3...pk问这些数字的异或值。
解题思路:这题首先要明确 x ^ y = V , x ^ z = W, 那么 y ^ z = V ^ W; 所以这题可以用并查集来做,因为只要两个数都和同一个数异或,那么他们就属于同一个集合,这样即使它们和一个数这个数的值是未知的,但是这两个数的异或值是可以知道的。多个数的异或值也是同样的,只要这些数两两和某个相同的值异或,那么就是可以知道的,如果出现了一个失配的那么就不能求,注意这里的某个值是这个值本身是未知的,如果已知的话,那么另一个值也是可以求出来的。然后就是I P V 的情况,我们不妨给他一个虚拟的节点,这样就可以和 I P Q V 一样了。然后所有的数和0的异或还是本身,所以初值是0.这题要求如果出现了两个事实相饽的,那么后面的也就不要再做了。
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 2e4 + 5; const int maxn = 4e4 + 5; int n, Q; int p[N]; int v[N]; struct Query { char type; int a, b, val; int k, l[100]; } q[maxn]; void init () { for (int i = 0; i <= n; i++) { p[i] = i; v[i] = 0; } } int getParent (const int a) { if (a == p[a]) return a; int t = p[a]; p[a] = getParent (p[a]); v[a] ^= v[t]; return p[a]; } void solve () { int cnt = 0; for (int i = 1; i <= Q; i++) { if (q[i].type == 'I') { cnt++; int p1 = getParent (q[i].a); int p2 = getParent (q[i].b); if (p1 == p2) { if ((v[p1] ^ v[q[i].a] ^ v[q[i].b]) != q[i].val) { printf ("The first %d facts are conflicting.\n", cnt); return; } } else { if (p1 == n) swap (p1, p2); p[p1] = p2; v[p1] = (v[q[i].a] ^ v[q[i].b] ^ q[i].val); } } else { int ans = 0; int parent[N]; bool flag = 1; memset (parent, 0, sizeof (parent)); for (int j = 0; j < q[i].k; j++) { getParent (q[i].l[j]); ans ^= v[q[i].l[j]]; if (p[q[i].l[j]] != n) parent[p[q[i].l[j]]] ^= 1; } for (int j = 0; j <= n; j++) { if (parent[j]) { flag = 0; break; } } if (flag) printf ("%d\n", ans); else printf ("I don't know.\n"); } } } int main () { char str[105]; int a, b, val; int cas = 0; while (scanf ("%d%d", &n, &Q) && (n || Q)) { init (); printf ("Case %d:\n", ++cas); for (int i = 1; i <= Q; i++) { scanf ("%s", str); q[i].type = str[0]; if (q[i].type == 'I') { gets(str); if (sscanf (str, "%d%d%d", &q[i].a, &q[i].b, &q[i].val) == 2) { q[i].val = q[i].b; q[i].b = n; } } else { scanf ("%d", &q[i].k); for (int j = 0; j < q[i].k; j++) scanf ("%d", &q[i].l[j]); } } solve(); printf ("\n"); } return 0; }
UVA12232 - Exclusive-OR(带权并查集)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。