【趣题&输入略坑】【并查集(带权)】NKOJ 3762 守夜人
2016-09-19 23:40
169 查看
NKOJ 3762 守夜人
时间限制 : - MS 空间限制 : 65536 KB
评测说明 : 时限1000ms
问题描述
鉴于john snow当选了新的守夜人总司令,艾里沙爵士感觉非常不爽,想搞点事情来难倒snow。艾里沙爵士告诉你有一个n项的序列X0,X1,X2…..Xn-1。(其中每一项均在int范围之内)但是你现在不知道其中的任何一项。艾里沙会逐步的告诉你一些信息并且问你一些问题。共有两种类型的信息和一种类型的询问。
I p v : tell you Xp = v
I p q v : tell you Xp XOR Xq = v
Q k p1 p2 … pk : 询问Xp1 XOR Xp2 XOR … XOR Xpk的值 k≤15
输入格式
会有多组测试数据但不会超过10组。
每一组数据以两个整数开始:n , Q(1 ≤ n ≤ 20, 000, 2 ≤ Q ≤ 40, 000)题目描述中的k是一个不大于15的整数。
最后一组数据为n==Q==0,不用进行运算。
输出格式
对于每组数据,输出第一行为数据的组数,接下来的每一行对应一次询问的答案。
如果根据前面给出的信息无法算出答案,则输出“I don’t know.”。
如果与已知信息冲突,输出“The first i facts are conflicting.”,并结束对于这一组数据的运算,其中i为这组数据出现过的的信息条数(不含询问,包含当前这一条信息)。
样例输入
2 6
I 0 1 3
Q 1 0
Q 2 1 0
I 0 2
Q 1 1
Q 1 0
3 3
I 0 1 6
I 0 2 2
Q 2 1 2
2 4
I 0 1 7
Q 2 0 1
I 0 1 8
Q 2 0 1
0 0
样例输出
Case 1:
I don’t know.
3
1
2
Case 2:
4
Case 3:
7
The first 2 facts are conflicting.
提示
注释:
鉴于两种I操作的输入比较麻烦,这里给出一种参考输入方法:
gets(s);
if(sscanf(s,”%d%d%d”,&a,&b,&v)==2)
//这一行输入了两个整数,要先除去行首的字母
{
…
}
来源 老王
思路:
并查集,将有关联的点加入一个集合,val[x]表示x^be[x].
特别的,建立一个虚拟点n,作为其所在集合的根,val
=0,即该集合中val[x]的值为x号本身。判断一个点是否已知,就看改点的集合根节点是否为n。
注意合并时,n优先作为父亲
对于Q,暴力枚举所有数,若已知,则^起来;若未知但be[x]出现次数为偶数,也可直接^起来,否则无解。
时间限制 : - MS 空间限制 : 65536 KB
评测说明 : 时限1000ms
问题描述
鉴于john snow当选了新的守夜人总司令,艾里沙爵士感觉非常不爽,想搞点事情来难倒snow。艾里沙爵士告诉你有一个n项的序列X0,X1,X2…..Xn-1。(其中每一项均在int范围之内)但是你现在不知道其中的任何一项。艾里沙会逐步的告诉你一些信息并且问你一些问题。共有两种类型的信息和一种类型的询问。
I p v : tell you Xp = v
I p q v : tell you Xp XOR Xq = v
Q k p1 p2 … pk : 询问Xp1 XOR Xp2 XOR … XOR Xpk的值 k≤15
输入格式
会有多组测试数据但不会超过10组。
每一组数据以两个整数开始:n , Q(1 ≤ n ≤ 20, 000, 2 ≤ Q ≤ 40, 000)题目描述中的k是一个不大于15的整数。
最后一组数据为n==Q==0,不用进行运算。
输出格式
对于每组数据,输出第一行为数据的组数,接下来的每一行对应一次询问的答案。
如果根据前面给出的信息无法算出答案,则输出“I don’t know.”。
如果与已知信息冲突,输出“The first i facts are conflicting.”,并结束对于这一组数据的运算,其中i为这组数据出现过的的信息条数(不含询问,包含当前这一条信息)。
样例输入
2 6
I 0 1 3
Q 1 0
Q 2 1 0
I 0 2
Q 1 1
Q 1 0
3 3
I 0 1 6
I 0 2 2
Q 2 1 2
2 4
I 0 1 7
Q 2 0 1
I 0 1 8
Q 2 0 1
0 0
样例输出
Case 1:
I don’t know.
3
1
2
Case 2:
4
Case 3:
7
The first 2 facts are conflicting.
提示
注释:
鉴于两种I操作的输入比较麻烦,这里给出一种参考输入方法:
gets(s);
if(sscanf(s,”%d%d%d”,&a,&b,&v)==2)
//这一行输入了两个整数,要先除去行首的字母
{
…
}
来源 老王
思路:
并查集,将有关联的点加入一个集合,val[x]表示x^be[x].
特别的,建立一个虚拟点n,作为其所在集合的根,val
=0,即该集合中val[x]的值为x号本身。判断一个点是否已知,就看改点的集合根节点是否为n。
注意合并时,n优先作为父亲
对于Q,暴力枚举所有数,若已知,则^起来;若未知但be[x]出现次数为偶数,也可直接^起来,否则无解。
#include<cstdio> #include<iostream> #include<sstream> using namespace std; const int need=20004; int val[need],be[need],cn[need]; //........................................................... int getbe(int x) { if(x!=be[x]) { int t=getbe(be[x]); val[x]^=val[be[x]]; return be[x]=t; } return x; } void addbe(int x,int fx,int y,int fy,int z) { be[fx]=fy; val[fx]=val[x]^val[y]^z; } //........................................................... string c; int cnt,k[17],a; void in_() { cnt=0; getline(cin,c,'\n'); stringstream os(c); while(os>>a) k[++cnt]=a; } //........................................................... int main() { //freopen("a.txt","r",stdin); int n,m,f1,f2,tot=0,ans2; char t; bool mark; while(true) { scanf("%d%d",&n,&m); if(n==0) return 0; printf("Case %d:\n",++tot); mark=true; ans2=0; for(int i=0;i<=n;i++) be[i]=i,val[i]=0; for(int i=1,j;i<=m;i++) { while(true) { t=getchar(); if(t=='I'||t=='Q') break; } in_(); if(!mark) continue; if(t=='I') { ans2++; if(cnt==3) { f1=getbe(k[1]),f2=getbe(k[2]); if(f1!=f2)//不在一个集合中,合并,若该集合所有节点已知,即有根节点为n,则n做合并后的根节点 { if(f1==n) addbe(k[2],f2,k[1],f1,k[3]);//有n就n做根节点 else addbe(k[1],f1,k[2],f2,k[3]); } else if((val[k[1]]^val[k[2]])!=k[3]) //若在同一集合,num[x]^num[y]=val[x]^val[fx]^val[y]^val[fy]=val[x]^val[y] { printf("The first %d facts are conflicting.\n",ans2); mark=false; } } else if(cnt==2) { f1=getbe(k[1]); if(f1!=n)//改点未知,改为已知,加入n集合中 { be[f1]=n; val[f1]=k[2]^val[k[1]];//val[fx]=num[fx]=num[x]^val[x] } else if(val[k[1]]!=k[2]) { printf("The first %d facts are conflicting.\n",ans2); mark=false; } } } else if(t=='Q') { for(j=0;j<=n;j++) cn[j]=0; int ans=0; bool flag=true; for(j=2;j<=cnt;j++) { f1=getbe(k[j]); if(f1!=n) cn[f1]++; ans^=val[k[j]]; } for(j=0;j<n;j++) if(cn[j]&1) { puts("I don't know."); flag=false; break; } if(flag) printf("%d\n",ans); } } } }
相关文章推荐
- NKOJ 3762 守夜人 (并查集)
- 【题】【DP(背包&状压)&输入略坑】NKOJ 3700 校长的烦恼
- Pku acm 2492 A Bug's Life数据结构题目解题报告(十)---- 并查集的应用
- C++ FAQ Lite[15]--通过 <iostream> 和 <cstdio>输入/输出(新)
- 解决xml中&符号"&amp;"输入问题的一个思路
- Boot.ini中输入Ansi控制码"ESC"
- ASP.NET中通过文本框的输入实现"拼音码"动态查询的效果
- clipse(MyEclipse) 输入"."号后老卡住,没响应
- 循环输入简洁写法&amp;amp;三选择语句嵌套
- JS验证输入只能是数字和"."这个符号
- ImageTTFBBox &amp;amp; any2eucjp 和jpgraph不能输入汉字的解决办法
- 关于开发在线网页编辑器按回车会输入<p>而不是<br>的解决方法
- ASP.NET2.0中"无法显示 XML 页。 使用 XSL 样式表无法查看 XML 输入。"问题的解决
- NET中"无法显示 XML 页。 使用 XSL 样式表无法查看 XML 输入。"
- 如何让诊断功能不需要输入APPS口令 &监控用户当前在使用那个表单?
- NET中"无法显示 XML 页。 使用 XSL 样式表无法查看 XML 输入。"问题的解决
- 通过例子学习正则表达式(二)--检查输入的"钱"
- 输入超出文件尾 解决方法 错误 '800a003e'
- java j2ee & java 限制文本输入框textarea最大输入字符的js
- 如何设置REUSE_ALV_GRID_DISPLAY'的单个单元格的是否可以输入[转]