题意:
      给你一个数组b[][],在给你一些关系,问是否可以找到一个满足限制的a[],

关系如下(图片):



思路:
      说到限制,而且还是两个两个之间的限制,那么很容易想到2-sat但是这个题目
扎一看还不像,b[i][j]不是只 0 1 2,怎么办呢,其实我们可以一位一位枚举,最多
也就32,对于每一位我们都判断下,只有所有的位数都满足了,才算存在a[],下面说下关键,就是怎么建图。

a[i] | a[j] == 0 说明两个都是0,则           a  ~a ,b ~b.
a[i] | a[j] == 1 说明两个至少有一个是1则    ~a  b ,~b a.
a[i] & a[j] == 1 说明两个都是1,则          ~a  a ,~b b.
a[i] & a[j] == 0 说明至少有一个0 则         b ~a  ,a ~b.
a[i] ^ a[j] == 1 说明两个不同 则            a ~b ,b ~a ,~a b ,~b a
a[i] ^ a[j] == 0 说明两个相同 则            a b ,b ,a ,~a ~b ,~b ~a

然后强连通判断是否可行就行了,这里说一下,之前我强连通用的全是双深搜的那个,一直都可以,知道今天这个题目一直超时,我一开始想不出超时的地方,只能是换了个强连通的算法,用的Tarjan结果1625ms AC了.蛋疼。


#include<stdio.h>
#include<string.h>
#include<stack>#define N_node 1000 + 50
#define N_edge 1000000 + 100

using namespace std;typedef struct
{int to ,next;
}STAR;STAR E[N_edge];
int list[N_node] ,tot;
int DFN[N_node] ,LOW[N_node];
int Belong[N_node];
int Index ,num ,okk;
int instack[N_node];
int B[550][550];
stack<int>st; void add(int a ,int b)
{E[++tot].to = b;E[tot].next = list[a];list[a] = tot;
}int minn(int x ,int y)
{return x < y ? x : y;
}void Tarjan(int s)
{DFN[s] = LOW[s] =  Index ++;st.push(s);instack[s] = 1;for(int k = list[s] ;k ;k = E[k].next){int to = E[k].to;if(!DFN[to]){Tarjan(to);LOW[s] = minn(LOW[to] ,LOW[s]);}else if(instack[to]){LOW[s] = minn(DFN[to] ,LOW[s]);    }}if(LOW[s] == DFN[s]){num ++; while(1){int v = st.top();Belong[v] = num;st.pop();instack[v] = 0;if(v == s) break;}}
}bool ok(int n)
{memset(instack ,0 ,sizeof(instack));memset(DFN ,0 ,sizeof(DFN));memset(LOW ,0 ,sizeof(LOW));while(!st.empty()) st.pop();Index = 1 ,num = 0;for(int i = 0 ;i < n * 2 ;i ++){if(DFN[i]) continue;Tarjan(i);}for(int i = 0 ;i < n * 2 ;i += 2)if(Belong[i] == Belong[i^1]) return 0;return 1;
}bool solve(int n )
{for(int i = 0 ;i < n ;i ++)if(B[i][i]) return 0;__int64 Key = 1;for(int ii = 1 ;ii <= 32 ;ii ++ ,Key *= 2){memset(list ,0 ,sizeof(list));tot = 1;for(int i = 0 ;i < n ;i ++)for(int j = 0 ;j < n ;j ++){if(i == j) continue;int now = B[i][j] & Key;if(i % 2 && j % 2){if(!now)add(i * 2 ,i * 2 + 1) ,add(j * 2 ,j * 2 + 1);else add(i * 2 + 1 ,j * 2) ,add(j * 2 + 1 ,i * 2);}else if(i % 2 == 0 && j % 2 == 0){if(!now) add(j * 2 ,i * 2 + 1) ,add(i * 2 ,j * 2 + 1);else add(i * 2 + 1 ,i * 2) ,add(j * 2 + 1 ,j * 2);}else{if(!now)add(i * 2 ,j * 2) ,add(i * 2 + 1 ,j * 2 + 1),add(j * 2 ,i * 2) ,add(j * 2 + 1 ,i * 2 + 1);elseadd(i * 2 ,j * 2 + 1) ,add(j * 2 ,i * 2 + 1),add(i * 2 + 1 ,j * 2) ,add(j * 2 + 1 ,i * 2);}}if(!ok(n)) return 0;}return 1;
} int main ()
{int n ,i ,j;while(~scanf("%d" ,&n)){for(i = 0 ;i < n ;i ++)for(j = 0 ;j < n ;j ++)scanf("%d" ,&B[i][j]);solve(n) ? puts("YES") : puts("NO");}return 0;
}           

hdu4421 2-sat(枚举二进制每一位)相关推荐

  1. 小技巧 ----- 通过二进制串的位运算进行一维指数型枚举

    一维指数型枚举 使用场景 给定n个水平方格 每个方格里面可以放1或0 那么所有存放的情况一共有2n2^n2n种 枚举出所有情况 二进制串的位运算结论 给定一个二进制串,如101011 从左到右可以规定 ...

  2. mysql 取二进制某一位_c语言中如何提取二进制数中的某一位?

    展开全部 下面是三种方式: ①通过模2除2(%2./2)的方法62616964757a686964616fe58685e5aeb931333366306434 num%2--取出二进制的最后一位 nu ...

  3. 【中级软考】位示图bitmap是什么?(利用二进制的一位来表示磁盘中的一个盘块的使用情况)

    位示图 位示图是利用二进制的一位来表示磁盘中的一个盘块的使用情况.当其值为"0"时,表示对应的盘块空闲:为"1"时,表示已经分配.有的系统把"0&qu ...

  4. C#枚举类型用户标志位的代码

    在写代码之余,把写代码过程比较好的一些代码段收藏起来,下面的代码是关于C#枚举类型用户标志位的代码,应该能对各位朋友有用处. enum Mammalia {Bison = 1,Human = 2,Ma ...

  5. 小技巧 ----- 通过二进制串的位运算进行二维指数型枚举

    二维指数型枚举 题目: 给定4x4矩阵(每个元素为1或0) 枚举出所有情况,在矩阵元素为1的位置执行turn()方法 思路: 把4x4方格看作一个一维的水平长度为16的方格 即现在需要枚举一个长度为1 ...

  6. c++ 输出二进制_【位运算与状态压缩】二进制的魅力

    [引言] 今天讲讲位运算与状态压缩.         位运算涉及系统底层的运算,骚操作很多:状态压缩则是编程中空间优化的有效手段,应该说两者本身其实并没有太直接的联系,但是在实际使用时会有一定的结合, ...

  7. 八进制数输出二进制c语言,C语言 某数输出二进制的某位

    如题: 输入一个整数,截取它对应的二进制位中从右到左的第8-11位(最右边为第0位). **输入格式要求:"%d" 提示信息:"请输入一个整数:" **输出格式 ...

  8. java取二进制其中两位_Java:二进制(原码、反码、补码)与位运算(示例代码)...

    一.二进制(原码.反码.补码) 二进制的最高位是符号位("0"代表正数,"1"代表负数): Java中没有无符号数: 计算机以整数的补码进行运算: 1.  原码 ...

  9. LeetCode 1178. 猜字谜(状态压缩+枚举二进制子集+哈希)

    文章目录 1. 题目 2. 解题 1. 题目 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件, ...

最新文章

  1. qt creator报错处理积累
  2. C++成员变量初始化顺序问题
  3. 和nptf螺纹一样吗_摩托车火花塞长短不同,对发动机有影响吗?
  4. windows.onload和body的onload属性的区别
  5. Spring定时任务并行(异步)处理
  6. ASP.NET MVC 学习之路-5
  7. MySQL: InnoDB 还是 MyISAM?
  8. 亲测!Jquery2.0不支持IE8-了
  9. 【2021团体程序设计天梯赛】L1部分(PTA,L1-073到L1-080)题解代码
  10. Java的八大常用类
  11. WEB前端超多知识总结
  12. 从入门到放弃:微信小程序入门个人指南Day 4
  13. 服务器硬件规格常用查看命令——CPU相关命令
  14. 4、ExtJs——Ext.window.Window
  15. 小米android的手机根目录,小米手机用re模式进行刷机。把rom放进根目录,根目录是哪里?...
  16. 嵌入式Linux热点分享网络(四)
  17. 如何用python实现地图数据可视化
  18. 微处理机就是微型计算机,他们是《微型计算机》改版20年的历史见证者
  19. FORTRAN学习笔记
  20. C语言推荐书籍pdf版附下载链接共30+本从入门到进阶带你走上大牛之路

热门文章

  1. 转:Linux下应用tgtadm构建iSCSI Target(SAN)
  2. 深度学习中 batchnorm 层是咋回事?
  3. 3dContactPointAnnotationTool开发日志(二二)
  4. 分享.Net 设计模式大全
  5. Win7命令终端基础配色指南
  6. eclipse中访问不了tomcat首页server Locations变灰无法编辑
  7. struts.xml 文件添加DTD文件
  8. Apache下PHP的几种工作方式
  9. hibernate Disabling contextual LOB creation as connection was null
  10. uva 11978 Fukushima Nuclear Blast (二分+多边形与圆交)