有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. hdu 1599 find the mincost route (最小环与floyd算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1599 find the mincost route Time Limit: 1000/2000 MS ...

  2. Django rest framework 版本控制(源码分析)

    基于上述分析 #2.处理版本信息 处理认证信息 处理权限信息 对用户的访问频率进行限制 self.initial(request, *args, **kwargs) #2.1处理版本信息 #versi ...

  3. exit()与_exit()区别

    exit()与_exit()都是用来终止进程的函数,当程序执行到两者函数时,系统将会无条件停止剩下操作,清除进程结构体相应信息,并终止进程运行. 二者的主要区别在于:exit()函数在执行时,系统会检 ...

  4. linux 自旋锁和信号量【转】

    转自:http://blog.csdn.net/xu_guo/article/details/6072823 版权声明:本文为博主原创文章,未经博主允许不得转载. 自旋锁最多只能被一个可执行线程持有( ...

  5. 2014ACM/ICPC亚洲区广州站题解

    这一场各种计算几何,统统没有做. HDU 5129 Yong Zheng's Death HDU 5136 Yue Fei's Battle

  6. STL之顺序容器 deque 动态数组

    deque是一个动态数组,deque与vector非常类似,vector是一个单向开口的连续线性空间,deque则是双向开口的连续线性空间.两者唯一的区别是deque可以在数组的开头和末尾插入和删除数 ...

  7. leetcode 121 122 123 . Best Time to Buy and Sell Stock

    121题目描述: 解题:记录浏览过的天中最低的价格,并不断更新可能的最大收益,只允许买卖一次的动态规划思想. class Solution { public: int maxProfit(vector ...

  8. 测试php单例模式和静态访问,实例化访问的效率

    // 测试的类class Memory { private static $a= null; public function __construct() { return self::$a; } pu ...

  9. java-增强for循环

    public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); lis ...

  10. mac下谷歌chrome浏览器的快捷键

    1. 标签页和窗口快捷键 ⌘-N 打开新窗口. ⌘-T 打开新标签页. ⌘-Shift-N 在隐身模式下打开新窗口. 按 ⌘-O,然后选择文件. 在 Chrome 浏览器中打开计算机中的文件. 按住  ...