有26张牌(A~Z),其中三张被拿走了。其余23张被分发给了两个人。给你m次调查结果,一次调查结果是对其中一个人询问一对牌,他会告诉你他有这对牌的几张(0~2)。问你有多少种被拿走的牌的组合。

三重循环枚举被拿走的牌。

然后对于一次调查,我们发现可能的十二种情况中({这两张牌都被拿走,都不被,其中一张被拿走,其中另一张被拿走} × {回答:0,1,2}),只有一种情况我们不能确定它们的归属,或者无解。即两张牌都不被拿走,并且回答是1。那么必然其中一张牌在一个人手上,另一张牌在另一人手上,但我们不能确定是那张。

其实这是个2-sat的XOR。

因为是双向边,我们可以直接用并查集。

然后有些牌的归属在一开始就已经被制定了。

如果A和!A在同一个并查集里边或者其并查集的取值都一开始确定,并且两者相同,那么无解。其他都有解。

#include<cstdio>
#include<cstring>
using namespace std;
int n,whi[55],xs[55],ans;
char op[55][4];
bool cho[105];
int beg[105];
int fa[105],val[105];
int find(int x){
return x==fa[x] ? x : fa[x]=find(fa[x]);
}
int main(){
// freopen("b.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%s%d%d",op[i],&whi[i],&xs[i]);
--whi[i];
}
for(int i='A';i<='Z';++i){
for(int j=i+1;j<='Z';++j){
for(int k=j+1;k<='Z';++k){
memset(beg,-1,sizeof(beg));
memset(val,-1,sizeof(val));
for(int p=1;p<=52;++p){
fa[p]=p;
}
cho[i]=cho[j]=cho[k]=1;
bool flag=1;
for(int p=1;p<=n;++p){
if(cho[op[p][0]] && cho[op[p][1]]){
if(xs[p]>=1){
flag=0;
break;
}
}
else if(cho[op[p][0]]){
if(xs[p]==0){
if(beg[op[p][1]]==whi[p]){
flag=0;
break;
}
beg[op[p][1]]=(whi[p]^1);
}
else if(xs[p]==1){
if(beg[op[p][1]]==(whi[p]^1)){
flag=0;
break;
}
beg[op[p][1]]=whi[p];
}
else{
flag=0;
break;
}
}
else if(cho[op[p][1]]){
if(xs[p]==0){
if(beg[op[p][0]]==whi[p]){
flag=0;
break;
}
beg[op[p][0]]=(whi[p]^1);
}
else if(xs[p]==1){
if(beg[op[p][0]]==(whi[p]^1)){
flag=0;
break;
}
beg[op[p][0]]=whi[p];
}
else{
flag=0;
break;
}
}
else{
if(xs[p]==0){
if(beg[op[p][0]]==whi[p] || beg[op[p][1]]==whi[p]){
flag=0;
break;
}
beg[op[p][0]]=beg[op[p][1]]=(whi[p]^1);
}
else if(xs[p]==2){
if(beg[op[p][0]]==(whi[p]^1) || beg[op[p][1]]==(whi[p]^1)){
flag=0;
break;
}
beg[op[p][0]]=beg[op[p][1]]=whi[p];
}
else{
int f1=find(op[p][0]-'A'+1),f2=find(op[p][1]-'A'+1+26);
fa[f1]=f2;
f1=find(op[p][0]-'A'+1+26),f2=find(op[p][1]-'A'+1);
fa[f2]=f1;
}
}
}
if(flag){
// if(i=='X' && j=='Y' && k=='Z'){
// i='X';
// }
for(int p='A';p<='Z';++p){
if(beg[p]!=-1){
int f=find(p-'A'+1);
if(val[f]==(beg[p]^1)){
flag=0;
break;
}
else{
val[f]=beg[p];
} f=find(p-'A'+1+26);
if(val[f]==beg[p]){
flag=0;
break;
}
else{
val[f]=(beg[p]^1);
}
}
}
if(flag){
for(int p='A';p<='Z';++p){
int f1=find(p-'A'+1),f2=find(p-'A'+1+26);
if(f1==f2 || (val[f1]==val[f2] && val[f1]!=-1)){
flag=0;
break;
}
}
if(flag){
++ans;
}
}
}
cho[i]=cho[j]=cho[k]=0;
}
}
}
printf("%d\n",ans);
return 0;
}

【并查集】Gym - 101128B - Black Vienna的更多相关文章

  1. Codeforces Gym 100463E Spies 并查集

    Spies Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463/attachments Desc ...

  2. Gym - 100625G Getting Through 计算几何+并查集

    http://codeforces.com/gym/100625/attachments/download/3213/2013-benelux-algorithm-programming-contes ...

  3. Gym 100814C Connecting Graph 并查集+LCA

    Description standard input/output Statements Alex is known to be very clever, but Walter does not be ...

  4. Tree Restoration Gym - 101755F (并查集)

    There is a tree of n vertices. For each vertex a list of all its successors is known (not only direc ...

  5. GYM 101173 F.Free Figurines(贪心||并查集)

    原题链接 题意:俄罗斯套娃,给出一个初始状态和终止状态,问至少需要多少步操作才能实现状态转化 贪心做法如果完全拆掉再重装,答案是p[i]和q[i]中不为0的值的个数.现在要求寻找最小步数,显然要减去一 ...

  6. Gym - 101243F Vitamins(思维+并查集)

    题意 有三种药丸,白色W>红色R>蓝色B,给你m个约束条件,问你n个药丸的颜色,不能确定颜色输出‘?’ 题解 如果1<2<3,只要找到2就能确定1和3的颜色 如果2=4,只要确 ...

  7. Gym - 101550A Artwork (并查集在线做法)

    题目链接 题意:给你一个n*m的网格图,初始时格点全白,每次可以将一段连续的格点涂黑.求出每次操作之后白色连通块的数量. 看了看网上的题解,基本全是离线的做法.其实这道题是有在线的做法的,利用了对偶图 ...

  8. 【随机化】【并查集】Gym - 100851J - Jump

    题意:交互题,有一个长度为n(偶数)的二进制串,你需要猜不超过n+500次猜到它.如果你猜的串与原串相同的位数为n,那么会返回n,如果为n/2,那么会返回n/2,否则都会返回零. 先random,直到 ...

  9. 【枚举】【并查集】Gym - 101243F - Vitamins

    题意:有n片药,有三种颜色,白色比红色重,红色比蓝色重,给你一些它们之间的重量关系,比如1>3,2=4之类,问你它们的颜色,如果没法判断的输出?. 先并查集把等于号全缩起来,然后按照大于号建图, ...

随机推荐

  1. js_微信分享,监听点击分享,分享成功,取消分享,分享失败回调

    2017-06-13 见代码: function weixinShare() { var links = links = "www.youku.com"; common.get_o ...

  2. Python eval 函数说明

    eval(str [,globals [,locals ]]) -- 函数将字符串str当成有效Python表达式来求值,并返回计算结果. 例 :  eval('3+4')         ==> ...

  3. Kill windows和linux 进程

    Windows

  4. Java案例之士兵作战功能实现

    实现的功能比较简单,主要用到了多态的,抽象类以及模板方法模式这几个知识点.效果图如下,哈哈 ,大神勿喷,后面我会把这些知识点详细介绍出来,即使Java学的不好,只要有一点其他语言基础或者没有应该都能看 ...

  5. send,recv,sendto,recvfrom ~转载

     send,recv,sendto,recvfrom send函数 int send( SOCKET s,    const char FAR *buf,    int len,    int fla ...

  6. 2012年Elsevier旗下Computer Science期刊最新SCI影响因子排名

    Latest Impact Factor figures from Elsevier's Computer Science Journals Medical Image Analysis Impact ...

  7. 菜鸟进阶之:VC++之Visual Studio中DLL调用实现

    C++写的DLL,用C++调用其实是一个比较简单的事情,调用DLL函数的方法其实有很多,说一个最普通的方法: 1.新建一个解决方案,文件->新建项目->Visual c++->win ...

  8. 【模板】SPOJ FACT0 大数分解 miller-rabin & pollard-rho

    http://www.spoj.com/problems/FACT0/en/ 给一个小于1e15的数,将他分解. miller-rabin & pollard-rho模板 #include & ...

  9. Makefile系列之三 : 变量

    一.变量的基础 变量在声明时需要给予初值,而在使用时,需要给在变量名前加上“$”符号,但最好用小括号“()”或是大括号“{}”把变量给包括起来.如果你要使用真实的“$”字符,那么你需要用“$$”来表示 ...

  10. cacti (可以利用yum安装cacti的配置)

    [root@localhost ~]# yum install -y epel-release[root@localhost ~]# [root@localhost ~]# yum install - ...