UVALive(LA) 4487 Exclusive-OR(带权并查集)
题意:对于n个数X[0]~X[n-1],但你不知道它们的值,通过逐步提供给你的信息,你的任务是根据这些信息回答问题,有三种信息如下:
I p v : Xp = v; Xp 的值为v
I p q v : Xp ^ Xq = v; Xp 异或Xq的值为v
Q k X1 X2 X3 ..... Xk : 问X1异或X2异或X3....异或Xk的值为多少?
解题思路:先看处理部分(I),有两种 I 一种 是后面有两个整数的,一种是后面有三个整数的,(这里的输入要注意整数有可能是好几个字符)。先看三个整数的,Xp ^ Xq = v;那么我们可以利用并查集把 使 p 的父节点 为 q,再建立一个数组w[],代表Xp 异或 根节点的值,我们对于每次给出的两个数,p 和 q,把它们并到集合里面,利用路径压缩使得w[p]和w[q]都是和根节点异或的值,在压缩的时候维护这个数组就好。
首先我们需要知道几个公式 a ^ b= c, 那么 a = b ^ c b = a ^ c;
异或运算有结合律,交换律。
a ^ a = 0;
a ^ 0 = a;
对于 I p q v : p ^ q = v;
假设:
fp 是 p 的根节点,那么 fp = p ^ w[p]; 1
fq 是 q 的根节点,那么 fq = q ^ w[q]; 2
p ^ q = v ; 3
我们把 fp 的父节点设为 fq(新的根节点) 那么 w[fp] = fp ^ fq; 4
把 1 2 3 式带到 4 式的 w[fp] = w[p] ^ w[q] ^ v;
这样就解决了路径压缩过程中的维护数组问题。对于 I 后面仅有 二个整数的情况,I p v p = v;我们可以变形一下 p ^ 0 = v;这样是不是就和上面那种情况很像了呢,即令 q = 0,就好了,因为 我们的编号是 0 ~ N- 1,为了不和其他节点弄混,那么我们可以把这个节点用编号 n 来表示,只不过已知 n 的值为 0 就好了~~~~,然后处理数据这部分就解决了~~~~
紧接着我们看询问部分(Q),询问的时候 假设 询问的是 X1,X2,X3..........Xn,
我们先看 w[X1] ^ w[X2]^w[X3]^....w[Xn],假设他们的根节点是 R(他们在一个集合里面),
那么w[X1] ^ w[X2]^w[X3]^....w[Xn]
= X1 ^R ^ X2 ^R ^ X3 ^ R ^ ......... ^ Xn ^ R
这里一共有 N 个 R ,由公式 a ^ a= 0; a ^ 0 = a;而且异或具有交换律,那么 这里的 N 如果是 偶数 我们 就可以求得X1 ^R ^ X2 ^R ^ X3 ^ R ^ ......... ^ Xn ^ R = X1 ^ X2 ^ X3 ^ ......^Xn,如果是奇数那么最后就会剩下一个单独的R。。。这里这个 R 是已知的话那么也可以求出来 ,怎么会是已知的呢?我们可以想想有一个特殊的 ,就是那个编号为 N 的节点,他的值是 0 ,所以就要分情况了
if(R是N)
{
X1 ^ X2 ^ X3 ^ ......^Xn =w[X1] ^ w[X2] ^ w[X3] ^....w[Xn];
}
else
{
if(R的数量是奇数)
{
不知道值;
}
else
{
X1 ^ X2 ^ X3 ^ ......^Xn =w[X1] ^ w[X2] ^ w[X3] ^....w[Xn];
}
}
这样整个过程就结束了。。。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <cctype> 7 #include <algorithm> 8 #include <queue> 9 #include <stack> 10 #include <map> 11 #include <set> 12 using namespace std; 13 14 const int MAXN = 2e4 + 3; 15 int pre[MAXN]; //存放的是父节点 16 int weight[MAXN]; //存放是与根节点的异或值 17 int xp[MAXN]; //询问时的数 18 int n; 19 20 int Find(int x) //带路径压缩的查找 21 { 22 // printf("1"); 23 if(x != pre[x]) 24 { 25 int fx = pre[x]; 26 pre[x] = Find(pre[x]); 27 weight[x] ^= weight[fx]; //维护数组 28 //printf("2"); 29 } 30 return pre[x]; 31 } 32 33 int mix(int x, int y, int z) 34 { 35 int fx = Find(x); 36 int fy = Find(y); 37 //printf("x = %d y = %d z = %d fx = %d fy = %d\n",x,y,z,fx,fy); 38 if(fx == fy) //如果给出的两个数已经出现过。判断现在给出的这个 I 是不是和以前的冲突(矛盾) 39 { 40 if((weight[x] ^ weight[y]) != z) //(出现了矛盾) 41 return 0; 42 return 1; 43 } 44 if(fx == n) fx ^= fy ^= fx ^= fy; //为了使得 n 成为 根节点 45 pre[fx] = fy; 46 weight[fx] = weight[x] ^ weight[y] ^ z; //fx 的父节点设为 fy(新的根节点)后维护weight[fx]的值 47 return 1; 48 } 49 50 int solv(int key) 51 { 52 int index[MAXN]={0}; 53 int ans = 0; 54 for(int i = 0; i < key ; i++) //查找森林中的每个树,统计 根节点被异或的次数 55 { 56 if(index[i]) continue; 57 int fi = Find(xp[i]); 58 int cnt = 0; 59 for(int j = i ; j < key; j++) 60 { 61 int fj = Find(xp[j]); 62 if(index[j] == 0 && fi == fj) 63 { 64 cnt++; 65 index[j] = 1; 66 ans ^= weight[xp[j]]; 67 } 68 } 69 if((cnt&1) && fi != n) //根节点被异或的次数是奇数 而且不是那个特殊的根节点 70 return -1; 71 } 72 return ans; 73 } 74 75 int main() 76 { 77 //freopen("in.cpp","r",stdin); 78 int Q; 79 int kas = 1; 80 while(scanf("%d%d",&n,&Q) && (n || Q)) 81 { 82 printf("Case %d:\n",kas++); 83 for(int i = 0; i <= MAXN; i++) //初始化 开始每个点都是一棵树,自身异或自身是 0 , 84 { 85 pre[i] = i; 86 weight[i] = 0; 87 } 88 int facts = 0; 89 int flag = 0; 90 while(Q--) 91 { 92 char order[2]={0}; 93 scanf("%s",order); 94 int p,q,v; 95 if(order[0] == 'I') 96 { 97 facts++; 98 getchar(); 99 char str[7]={0}; 100 gets(str); 101 int k = 0; 102 for(int i = 0; str[i] != '\0'; i++) 103 if(str[i] == ' ') k++; 104 if(k == 1) 105 { 106 sscanf(str,"%d%d",&p,&v); //I 后面只有两个数 107 q = n; 108 } 109 else 110 { 111 sscanf(str,"%d%d%d",&p,&q,&v);//I 后面只有三个数 112 } 113 if(flag) continue; //矛盾 114 if(mix(p,q,v) == 0) //矛盾了 115 { 116 printf("The first %d facts are conflicting.\n",facts); 117 flag = 1; 118 } 119 } 120 else if(order[0] == 'Q') 121 { 122 int k; 123 scanf("%d",&k); 124 memset(xp,0,sizeof(xp)); 125 for(int i = 0; i < k; i++) 126 { 127 scanf("%d",&xp[i]); 128 } 129 if(flag) continue;//矛盾 130 int ans = solv(k); 131 if(ans == -1) 132 { 133 printf("I don't know.\n"); 134 } 135 else 136 printf("%d\n",ans); 137 } 138 } 139 printf("\n"); 140 } 141 return 0; 142 }
转载于:https://www.cnblogs.com/Ash-ly/p/5397649.html
UVALive(LA) 4487 Exclusive-OR(带权并查集)相关推荐
- 2017乌鲁木齐ICPC: I. A Possible Tree(带权并查集)
I. A Possible Tree Alice knows that Bob has a secret tree (in terms of graph theory) with n nodes wi ...
- 2017乌鲁木齐区域赛I(带权并查集)
#include<bits/stdc++.h> using namespace std; int f[200010];//代表元 long long rl[200010];//记rl[i] ...
- BZOJ 2303 方格染色(带权并查集)
要使得每个2*2的矩形有奇数个红色,如果我们把红色记为1,蓝色记为0,那么我们得到了这2*2的矩形里的数字异或和为1. 对于每个方格则有a(i,j)^a(i-1,j)^a(i,j-1)^a(i-1,j ...
- POJ1703带权并查集(距离或者异或)
题意: 有两个黑社会帮派,有n个人,他们肯定属于两个帮派中的一个,然后有两种操作 1 D a b 给出a b 两个人不属于同一个帮派 2 A a b 问a b 两个人关系 输出 同一个帮派 ...
- POJ1988(带权并查集,搬砖块)
题意: 可以这样理解,有n快方形积木,一开始都是单独的放到哪,然后有两种操作 1 M a b 把a所在的那一堆落到b所在那一堆的上面(一开始自己是一堆) 2 C a 问a下面有多少个积木 ...
- LA3027简单带权并查集
题意: 有n个点,一开始大家都是独立的点,然后给出一些关系,a,b表示a是b的父亲节点,距离是abs(a-b)%1000,然后有一些询问,每次询问一个节点a到父亲节点的距离是多少? 思路: ...
- hdu3234 带权并查集(XOR)
题意: 给你n个未知的正整数,有三总操作 I P V P的值是V I P Q V P XOR Q = V Q K ...
- hdu4829 带权并查集(题目不错)
题意: Information Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...
- poj1182 and 携程预赛2第一题 带权并查集
题意: 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底 ...
- How Many Answers Are Wrong HDU - 3038(带权并查集经典题,满满的都是注释)
How Many Answers Are Wrong HDU - 3038 点击打开链接 题意:现在有n个数(你并不知道这n个数是什么),m次查询,每次查询给出u,v,w.表示从第u个数到第v个数的 ...
最新文章
- 微软 Internet 信息服务器(IIS) 5.0 和 6.0 状态代码说明
- 关于java文件扩展名认识
- Mathematica初学者第一讲
- 直接插入排序比较次数_插入排序(C++)
- SDUTRescue The Princess(数学问题)
- linux系统内核官网,五年26个版本:Linux系统内核全程回顾
- 排序算法-02直接插入(python实现)
- 架构为什么要以领域为核心
- 腾讯开奖,应届生年薪40万,白菜价,薪资倒挂!
- Python版猜数游戏
- 什么叫侧面指纹识别_哪种指纹识别方式好?侧边指纹识别可能会成为主流
- php 脚本调试,PHP 调试脚本
- linux 删除进程的多种方法
- Java并发编程:进程和线程之由来__进程让操作系统的并发性成为可能,而线程让进程的内部并发成为可能...
- 中国电信业的魔咒:第四运营商之梦
- js加载flv格式视频
- php高德行政区边界,请教 高德地图绘制行政区划边界
- Java入门第65课——根据周长计算不同形状图形的面积
- 信息相关的术语缩略词_为什么您应该停止使用大词和行业术语(以及该怎么做)
- MySql NTERVAL函数
热门文章
- 万字长文带来2021最稳C/C++学习路线
- win7计算机系统减肥,win7系统精简瘦身的操作方法
- html设置div大小位置不变,div大小 div固定大小设置
- 用计算机绘制三维设计图步骤,3d效果图一般制作步骤
- Pycharm处理 E501 line too long 警告
- Mysql之Specified key was too long; max key length is 767 bytes
- cmyk rgb 数值转换_计算机视觉学习笔记2 图像类型转换
- php网易云信短信接口,短信接口指南
- 20021年还需要学C语言吗?C语言成为专家的路径、方法、书籍推荐
- 动物基因组测序基础分析流程总结(GWAS全流程第一部分:WGS基础流程)