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];
}
}
这样整个过程就结束了。。。。。
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <cmath>
- #include <cctype>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #include <map>
- #include <set>
- using namespace std;
- const int MAXN = 2e4 + ;
- int pre[MAXN]; //存放的是父节点
- int weight[MAXN]; //存放是与根节点的异或值
- int xp[MAXN]; //询问时的数
- int n;
- int Find(int x) //带路径压缩的查找
- {
- // printf("1");
- if(x != pre[x])
- {
- int fx = pre[x];
- pre[x] = Find(pre[x]);
- weight[x] ^= weight[fx]; //维护数组
- //printf("2");
- }
- return pre[x];
- }
- int mix(int x, int y, int z)
- {
- int fx = Find(x);
- int fy = Find(y);
- //printf("x = %d y = %d z = %d fx = %d fy = %d\n",x,y,z,fx,fy);
- if(fx == fy) //如果给出的两个数已经出现过。判断现在给出的这个 I 是不是和以前的冲突(矛盾)
- {
- if((weight[x] ^ weight[y]) != z) //(出现了矛盾)
- return ;
- return ;
- }
- if(fx == n) fx ^= fy ^= fx ^= fy; //为了使得 n 成为 根节点
- pre[fx] = fy;
- weight[fx] = weight[x] ^ weight[y] ^ z; //fx 的父节点设为 fy(新的根节点)后维护weight[fx]的值
- return ;
- }
- int solv(int key)
- {
- int index[MAXN]={};
- int ans = ;
- for(int i = ; i < key ; i++) //查找森林中的每个树,统计 根节点被异或的次数
- {
- if(index[i]) continue;
- int fi = Find(xp[i]);
- int cnt = ;
- for(int j = i ; j < key; j++)
- {
- int fj = Find(xp[j]);
- if(index[j] == && fi == fj)
- {
- cnt++;
- index[j] = ;
- ans ^= weight[xp[j]];
- }
- }
- if((cnt&) && fi != n) //根节点被异或的次数是奇数 而且不是那个特殊的根节点
- return -;
- }
- return ans;
- }
- int main()
- {
- //freopen("in.cpp","r",stdin);
- int Q;
- int kas = ;
- while(scanf("%d%d",&n,&Q) && (n || Q))
- {
- printf("Case %d:\n",kas++);
- for(int i = ; i <= MAXN; i++) //初始化 开始每个点都是一棵树,自身异或自身是 0 ,
- {
- pre[i] = i;
- weight[i] = ;
- }
- int facts = ;
- int flag = ;
- while(Q--)
- {
- char order[]={};
- scanf("%s",order);
- int p,q,v;
- if(order[] == 'I')
- {
- facts++;
- getchar();
- char str[]={};
- gets(str);
- int k = ;
- for(int i = ; str[i] != '\0'; i++)
- if(str[i] == ' ') k++;
- if(k == )
- {
- sscanf(str,"%d%d",&p,&v); //I 后面只有两个数
- q = n;
- }
- else
- {
- sscanf(str,"%d%d%d",&p,&q,&v);//I 后面只有三个数
- }
- if(flag) continue; //矛盾
- if(mix(p,q,v) == ) //矛盾了
- {
- printf("The first %d facts are conflicting.\n",facts);
- flag = ;
- }
- }
- else if(order[] == 'Q')
- {
- int k;
- scanf("%d",&k);
- memset(xp,,sizeof(xp));
- for(int i = ; i < k; i++)
- {
- scanf("%d",&xp[i]);
- }
- if(flag) continue;//矛盾
- int ans = solv(k);
- if(ans == -)
- {
- printf("I don't know.\n");
- }
- else
- printf("%d\n",ans);
- }
- }
- printf("\n");
- }
- return ;
- }
UVALive(LA) 4487 Exclusive-OR(带权并查集)的更多相关文章
- UVALive 3027 Corporative Network (带权并查集)
题意: 有 n 个节点,初始时每个节点的父节点都不存在,你的任务是执行一次 I 操作 和 E 操作,含义如下: I u v : 把节点 u 的父节点设为 v ,距离为| u - v | ...
- UVALive 3027 Corporative Network 带权并查集
Corporative Network A very big corporation is developing its corporative networ ...
- POJ1733 Party game [带权并查集or扩展域并查集]
题目传送 Parity game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10870 Accepted: 4182 ...
- POJ 1703 Find them, Catch them(带权并查集)
传送门 Find them, Catch them Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 42463 Accep ...
- [NOIP摸你赛]Hzwer的陨石(带权并查集)
题目描述: 经过不懈的努力,Hzwer召唤了很多陨石.已知Hzwer的地图上共有n个区域,且一开始的时候第i个陨石掉在了第i个区域.有电力喷射背包的ndsf很自豪,他认为搬陨石很容易,所以他将一些区域 ...
- poj1417 带权并查集 + 背包 + 记录路径
True Liars Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 2713 Accepted: 868 Descrip ...
- poj1984 带权并查集(向量处理)
Navigation Nightmare Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 5939 Accepted: 2 ...
- 【BZOJ-4690】Never Wait For Weights 带权并查集
4690: Never Wait for Weights Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 88 Solved: 41[Submit][ ...
- hdu3038(带权并查集)
题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 题意: n表示有一个长度为n的数组, 接下来有m行形如x, y, d的输入, 表示 ...
随机推荐
- ASP.NET Core [3]:进入HttpContext的世界(笔记)
原文链接:http://www.cnblogs.com/RainingNight/p/httpcontext-in-asp-net-core.html HttpContext是ASP.NET中的核心对 ...
- React跨域问题解决
https://segmentfault.com/q/1010000012732581 非跨域问题报错 -rpccorsdomain="http://localhost:3000" ...
- 第二阶段团队冲刺-four
昨天: 绘制logo. 今天: 用servlet完成名单打印功能. 遇到的问题: servlet中的获得的路径不是想要的.
- SVN客户端使用手册
使用svn进行源代码版本控制,代码管理利器. 优点: 使用方便,与文件管理器集成.速度快,稳定. 实现代码比较,比如对历史和当前代码进行比较. 解决多人同时编写代码时代码重复修改困难. 安装: 下载网 ...
- Access连接字符串
Access2007没有密码连接: <connectionStrings> <add name="myconn" connectionString="P ...
- select chosen 禁用下拉框某一个option
$("#tbParBudCode option[value='" + budCodeId + "']").attr("disabled", ...
- [洛谷P2801]教主的魔法
题目大意:有$n$个数,$q$个操作.两种操作: $M\;l\;r\;w:$把$[l,r]$所有数加上$w$ $A\;l\;r\;c:$查询$[l,r]$内大于等于$c$的元素的个数. 题解:分块,对 ...
- spring3创建RESTFul Web Service
spring 3支持创建RESTFul Web Service,使用起来非常简单.不外乎一个@ResponseBody的问题. 例如:后台controller: 做一个JSP页面,使用ajax获取数据 ...
- js函数形参和实参的区别
在<Javascript权威指南>中这样定义: 参数有形参(parameter)和实参(argument)的区别,形参相当于函数中定义的变量,实参是在运行时的函数调用时传入的参数. 说明白 ...
- lesson 5
C#中的委托(delegate)与事件(event) 一.委托就是中间人的意思,c#中的委托允许将一个类中的方法传递给另一个能调用该方法的类的某个对象.程序员可以将A类的一个方法m(被包含在某个del ...