【题意】

这个函数是给A求B的,现在给你B,问你是否能有A的解存在。

【2-SAT解法】

对于每个A[i]的每一位运行2-sat算法,只要跑到强连通就可以结束,应为只要判断是否有解,后面拓扑求解就不需要了。构图和算法思想和基本的2-sat一致,详见我的2-sat博文。

 #include <stdio.h>
#include <string.h>
inline int min(int a,int b){return a>b?b:a;}
struct edge
{
int v,next;
edge(int d=,int n=-):v(d),next(n){}
void set(int d,int n){v=d;next=n;}
}data[*];
int head[],hn;
void adde(int a,int b)
{
data[hn].set(b,head[a]);
head[a]=hn++;
}
int n;
int b[][];
int dfn[],low[],sta[],belong[];
bool ifin[];
int top,group,dep;
void tarjan(int u)
{
dfn[u]=low[u]=++dep;
sta[++top]=u;
ifin[u]=true;
for (int i=head[u];i!=-;i=data[i].next)
{
int v=data[i].v;
if (!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
} else
{
if (ifin[v]) low[u]=min(low[u],dfn[v]);
}
}
if (dfn[u]==low[u])
{
int j;
++group;
do
{
j=sta[top--];
belong[j]=group;
ifin[j]=false;
} while (u!=j);
}
}
void init()
{
hn=dep=group=;
top=-;
memset(head,-,sizeof head);
memset(dfn,,sizeof dfn);
memset(ifin,false,sizeof ifin);
}
bool judge()
{
for (int i=;i<n;++i)
if (belong[i]==belong[i+n]) return false;
return true;
}
bool solve()
{
for (int i=;i<n;++i)
for (int j=i;j<n;++j)
{
if (i==j && b[i][j]) return false;
if (b[i][j]!=b[j][i]) return false;
}
for (int k=;k<;++k)
{
init();
for (int i=;i<n;++i)
for (int j=i;j<n;++j)
{
int m=b[i][j]&(<<k);
if (i==j) continue;
if (i& && j&) // |
{
if (m)
{
adde(i,j+n);
adde(j,i+n);
} else
{
adde(i+n,i);
adde(j+n,j);
}
} else if (!(i&) && !(j&)) //&
{
if (m)
{
adde(i,i+n);
adde(j,j+n);
} else
{
adde(i+n,j);
adde(j+n,i);
}
} else // ^
{
if (m)
{
adde(i,j+n);
adde(j,i+n);
adde(j+n,i);
adde(i+n,j);
} else //==
{
adde(i,j);
adde(j,i);
adde(i+n,j+n);
adde(j+n,i+n);
}
}
}
for (int i=;i<(n<<);++i)
if (!dfn[i]) tarjan(i);
if (!judge()) return false;
}
return true;
}
int main()
{
while (~scanf("%d",&n))
{
for (int i=;i<n;++i)
for (int j=;j<n;++j)
scanf("%d",&b[i][j]);
if (solve()) puts("YES"); else puts("NO");
}
}

2-sat

【并查集】

主要思想是以A中每个元素的每一位作为一个基本单位,根据b中的值来确定每一位之间的等价关系,值相等的并在一个集合,每当能确定一个新的关系时验证原先的关系是否矛盾。不过在处理的时候有点小技巧,与2-sat的思想类似,扩充成2N个点,对于每一位,有个点代表其值,另一点代表其值的反。能确定一位的值时要同时更新这2点,从一方面说是充分发掘信息,另一方面说是为了异或运算的判断服务,因为异或不能确定一个值,但能确定相对关系,需要用到反。

并查集的算法在这题里比2-SAT的快,剩了些不必要的计算,思想也挺巧妙的。

 #include <stdio.h>
#include <string.h>
#define N 501*32
#define m1 mset.find(1)
#define m0 mset.find(0)
struct myset
{
int uset[*+];
myset(){init();};
void init(){memset(uset,-,sizeof uset);}
int find(int k)
{
if (uset[k]==-) return k;
return uset[k]=find(uset[k]);
}
void uion(int a,int b)
{
int aa=find(a);
int bb=find(b);
if (aa==bb) return;
uset[aa]=bb;
}
}mset;
int b[][],n;
bool solve()
{
for (int i=;i<n;++i)
for (int j=i;j<n;++j)
{
if (i==j && b[i][j]) return false;
if (b[i][j]!=b[j][i]) return false;
}
for (int i=;i<n;++i)
for (int j=;j<n;++j)
{
if (i==j) continue;
if (i& && j&)
{
for (int k=;k<;++k)
{
if (b[i][j]&(<<k) == )
{
int p1=i*+k+;
int p2=j*+k+;
if (mset.find(p1)==m1 || mset.find(p2)==m1 || mset.find(p1)==mset.find(p2+N)) return false;
mset.uion(p1,);
mset.uion(p2,);
mset.uion(p1+N,);
mset.uion(p2+N,);
}
}
} else
if (!(i&) && !(j&))
{
for (int k=;k<;++k)
{
if (b[i][j]&(<<k))
{
int p1=i*+k+;
int p2=j*+k+;
if (mset.find(p1)==m0 || mset.find(p2)==m0 || mset.find(p1)==mset.find(p2+N)) return false;
mset.uion(p1,);
mset.uion(p2,);
mset.uion(p1+N,);
mset.uion(p2+N,);
}
}
} else
{
for (int k=;k<;++k)
{
int p1=i*+k+;
int p2=j*+k+;
if (b[i][j]&(<<k))
{
if (mset.find(p1)==mset.find(p2)) return false;
mset.uion(p1,p2+N);
mset.uion(p2,p1+N);
} else
{
if (mset.find(p1)==mset.find(p2+N) ) return false;
mset.uion(p1,p2);
mset.uion(p1+N,p2+N);
}
}
}
}
return true;
}
int main()
{
while (~scanf("%d",&n))
{
mset.init();
for (int i=;i<n;++i)
for (int j=;j<n;++j)
scanf("%d",&b[i][j]);
if (solve()) puts("YES"); else puts("NO");
}
}

并查集

hdu 4421 Bit Magic的更多相关文章

  1. HDU 4421 Bit Magic(2-sat)

    HDU 4421 Bit Magic pid=4421" target="_blank" style="">题目链接 题意:就依据题目,给定b数 ...

  2. HDU 4421 Bit Magic(奇葩式解法)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4421 题目大意: 给了你一段代码, 用一个数组的数 对其进行那段代码的处理,是可以得到一个矩阵 让你判 ...

  3. HDU 4421 Bit Magic (图论-2SAT)

    Bit Magic Problem Description Yesterday, my teacher taught me about bit operators: and (&), or ( ...

  4. 图论(2-sat):HDU 4421 Bit Magic

    Bit Magic Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  5. hdu 3183 A Magic Lamp(RMQ)

    题目链接:hdu 3183 A Magic Lamp 题目大意:给定一个字符串,然后最多删除K个.使得剩下的组成的数值最小. 解题思路:问题等价与取N-M个数.每次取的时候保证后面能取的个数足够,而且 ...

  6. hdu 3183 A Magic Lamp RMQ ST 坐标最小值

    hdu 3183 A Magic Lamp RMQ ST 坐标最小值 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3183 题目大意: 从给定的串中挑 ...

  7. HDU 3183.A Magic Lamp-区间找最小值-RMQ(ST)

    A Magic Lamp Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  8. HDU 4421 ZOJ 3656 Bit Magic

    2-SAT,不要所有位置全部建好边再判断,那样会MLE的. 正解是,每一位建好边,就进行一次2-SAT. #include<cstdio> #include<cstring> ...

  9. HDU 3183 - A Magic Lamp - [RMQ][ST算法]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3183 Problem DescriptionKiki likes traveling. One day ...

随机推荐

  1. c\c++ 字符串处理大集合[转]

    rember this strncpy(a,b,); a[]='\0'; ]; memset(a,'#',sizeof(a)); a[]='\0'; 刚开始学C/C++时,一直对字符串处理函数一知半解 ...

  2. 安装配置tomcat环境

    安装配置tomcat环境 #所需要软件包 apache-tomcat-7.0.65.tar.gz    jdk-7u80-linux-x64.gz    #建立 个专用账户 usradd tomcat ...

  3. 六分钟学会创建Oracle表空间的步骤

    经过长时间学习创建Oracle表空间,于是和大家分享一下,看完本文你肯定有不少收获,希望本文能教会你更多东西. 1.先查询空闲空间 select tablespace_name,file_id,blo ...

  4. vs2010代码注释自动生成api文档

    最近做了一些接口,提供其他人调用,要写个api文档,可是我想代码注释已经写了说明,能不能直接把代码注释生成api?于是找到以下方法 环境:vs2010 先下载安装Sandcastle 和Sandcas ...

  5. ARM&Linux 下驱动开发第三节

    后台驱动代码如下:比较昨天的,添加了读写指针位置移动操作 #include<linux/init.h> #include<linux/module.h> #include< ...

  6. 移动端折腾国外分享(facebook、twitter、linkedin)

    一.前言 国内做HTML5页面,关注最多就是微信分享了,之前也写过关于微信分享的文章,可以点击查看:分享相关文章 再者,就是国内的其它分享,比如常用的新浪微博.腾讯微博.QQ空间等等,最方便的就是直接 ...

  7. centos 6.3 搭建git/gitosis/gitweb

    1. git的安装和配置 (1)使用yum源安装git yum install git (2)创建git用户并设置密码 #useradd --home /home/git git #passwd gi ...

  8. innobackupex的备份和恢复

      http://blog.itpub.net/15480802/viewspace-1173479/ 1 原理 分3个阶段:备份backup – 预恢复prepare  -- 恢复restore 注 ...

  9. MySQL mysqldump数据导出详解 --dump-slave 注意事项

    http://www.cnblogs.com/chenmh/p/5300370.html 介绍 在日常维护工作当中经常会需要对数据进行导出操作,而mysqldump是导出数据过程中使用非常频繁的一个工 ...

  10. Linux下判断cpu物理个数、几核

    自己服务器的输出 1. 查看物理CPU的个数   #cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l    1 2. 查 ...