hdu4421 2-sat(枚举二进制每一位)
题意:
给你一个数组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(枚举二进制每一位)相关推荐
- 小技巧 ----- 通过二进制串的位运算进行一维指数型枚举
一维指数型枚举 使用场景 给定n个水平方格 每个方格里面可以放1或0 那么所有存放的情况一共有2n2^n2n种 枚举出所有情况 二进制串的位运算结论 给定一个二进制串,如101011 从左到右可以规定 ...
- mysql 取二进制某一位_c语言中如何提取二进制数中的某一位?
展开全部 下面是三种方式: ①通过模2除2(%2./2)的方法62616964757a686964616fe58685e5aeb931333366306434 num%2--取出二进制的最后一位 nu ...
- 【中级软考】位示图bitmap是什么?(利用二进制的一位来表示磁盘中的一个盘块的使用情况)
位示图 位示图是利用二进制的一位来表示磁盘中的一个盘块的使用情况.当其值为"0"时,表示对应的盘块空闲:为"1"时,表示已经分配.有的系统把"0&qu ...
- C#枚举类型用户标志位的代码
在写代码之余,把写代码过程比较好的一些代码段收藏起来,下面的代码是关于C#枚举类型用户标志位的代码,应该能对各位朋友有用处. enum Mammalia {Bison = 1,Human = 2,Ma ...
- 小技巧 ----- 通过二进制串的位运算进行二维指数型枚举
二维指数型枚举 题目: 给定4x4矩阵(每个元素为1或0) 枚举出所有情况,在矩阵元素为1的位置执行turn()方法 思路: 把4x4方格看作一个一维的水平长度为16的方格 即现在需要枚举一个长度为1 ...
- c++ 输出二进制_【位运算与状态压缩】二进制的魅力
[引言] 今天讲讲位运算与状态压缩. 位运算涉及系统底层的运算,骚操作很多:状态压缩则是编程中空间优化的有效手段,应该说两者本身其实并没有太直接的联系,但是在实际使用时会有一定的结合, ...
- 八进制数输出二进制c语言,C语言 某数输出二进制的某位
如题: 输入一个整数,截取它对应的二进制位中从右到左的第8-11位(最右边为第0位). **输入格式要求:"%d" 提示信息:"请输入一个整数:" **输出格式 ...
- java取二进制其中两位_Java:二进制(原码、反码、补码)与位运算(示例代码)...
一.二进制(原码.反码.补码) 二进制的最高位是符号位("0"代表正数,"1"代表负数): Java中没有无符号数: 计算机以整数的补码进行运算: 1. 原码 ...
- LeetCode 1178. 猜字谜(状态压缩+枚举二进制子集+哈希)
文章目录 1. 题目 2. 解题 1. 题目 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件, ...
最新文章
- qt creator报错处理积累
- C++成员变量初始化顺序问题
- 和nptf螺纹一样吗_摩托车火花塞长短不同,对发动机有影响吗?
- windows.onload和body的onload属性的区别
- Spring定时任务并行(异步)处理
- ASP.NET MVC 学习之路-5
- MySQL: InnoDB 还是 MyISAM?
- 亲测!Jquery2.0不支持IE8-了
- 【2021团体程序设计天梯赛】L1部分(PTA,L1-073到L1-080)题解代码
- Java的八大常用类
- WEB前端超多知识总结
- 从入门到放弃:微信小程序入门个人指南Day 4
- 服务器硬件规格常用查看命令——CPU相关命令
- 4、ExtJs——Ext.window.Window
- 小米android的手机根目录,小米手机用re模式进行刷机。把rom放进根目录,根目录是哪里?...
- 嵌入式Linux热点分享网络(四)
- 如何用python实现地图数据可视化
- 微处理机就是微型计算机,他们是《微型计算机》改版20年的历史见证者
- FORTRAN学习笔记
- C语言推荐书籍pdf版附下载链接共30+本从入门到进阶带你走上大牛之路
热门文章
- 转:Linux下应用tgtadm构建iSCSI Target(SAN)
- 深度学习中 batchnorm 层是咋回事?
- 3dContactPointAnnotationTool开发日志(二二)
- 分享.Net 设计模式大全
- Win7命令终端基础配色指南
- eclipse中访问不了tomcat首页server Locations变灰无法编辑
- struts.xml 文件添加DTD文件
- Apache下PHP的几种工作方式
- hibernate Disabling contextual LOB creation as connection was null
- uva 11978 Fukushima Nuclear Blast (二分+多边形与圆交)