hdu 4421 Bit Magic
【题意】

这个函数是给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的更多相关文章
- HDU 4421 Bit Magic(2-sat)
HDU 4421 Bit Magic pid=4421" target="_blank" style="">题目链接 题意:就依据题目,给定b数 ...
- HDU 4421 Bit Magic(奇葩式解法)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4421 题目大意: 给了你一段代码, 用一个数组的数 对其进行那段代码的处理,是可以得到一个矩阵 让你判 ...
- HDU 4421 Bit Magic (图论-2SAT)
Bit Magic Problem Description Yesterday, my teacher taught me about bit operators: and (&), or ( ...
- 图论(2-sat):HDU 4421 Bit Magic
Bit Magic Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- hdu 3183 A Magic Lamp(RMQ)
题目链接:hdu 3183 A Magic Lamp 题目大意:给定一个字符串,然后最多删除K个.使得剩下的组成的数值最小. 解题思路:问题等价与取N-M个数.每次取的时候保证后面能取的个数足够,而且 ...
- hdu 3183 A Magic Lamp RMQ ST 坐标最小值
hdu 3183 A Magic Lamp RMQ ST 坐标最小值 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3183 题目大意: 从给定的串中挑 ...
- 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 ...
- HDU 4421 ZOJ 3656 Bit Magic
2-SAT,不要所有位置全部建好边再判断,那样会MLE的. 正解是,每一位建好边,就进行一次2-SAT. #include<cstdio> #include<cstring> ...
- HDU 3183 - A Magic Lamp - [RMQ][ST算法]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3183 Problem DescriptionKiki likes traveling. One day ...
随机推荐
- android 获取手机型号,本机电话号码,SDK版本以及firmwarw版本号(即系统版本号)
Android开发平台中,可通过TelephonyManager 获取本机号码. TelephonyManager phoneMgr=(TelephonyManager)this.getSystemS ...
- HTML5 ajax上传附件
var fd = new FormData(); fd.append('/*键值*/', this.files[0]);var xhr = new XMLHttpRequest ...
- 30.怎样在Swift中添加运行时属性?
和OC一样,Swift中也可以添加运行时属性.下面将提供一个完整的例子,演示如何给按钮点击事件添加运行时属性. 1.示例 import UIKit var s_GofButtonTouchDownKe ...
- (5)html表单
本节解说: html的表单. form * <form> 标签用于为用户输入创建 HTML 表单. 表单能够包含 input 元素,比如文本字段.复选框.单选框.提交按钮等等. * < ...
- dmalloc 原文 翻译整理
http://blog.csdn.net/cardinal_508/article/details/5553387 L13 从快速入门开始(Quickstart) 这个库是一个文件中所有简化用法中最常 ...
- 将Excel另存为CSV格式文件
直接将Excel另存为CSV,速度很快: $CurrentPath = $MyInvocation.MyCommand.Path.substring(0,$MyInvocation.MyCommand ...
- c++训练营--重载
// demo1.cpp : 定义控制台应用程序的入口点. //通过此例程了解重载 #include "stdafx.h" #include <iostream> us ...
- 基于jQuery 常用WEB控件收集
Horizontal accordion: jQuery 基于jQuery开发,非常简单的水平方向折叠控件. Horizontal accordion: jQuery jQuery-Horizonta ...
- js日期计算及快速获取周、月、季度起止日
var now = new Date(); //当前日期 var nowDayOfWeek = (now.getDay() == 0) ? 7 : now.getDay() - 1; //今天是本周的 ...
- 看来是要改用Gecko的节奏,放弃Awesomium吧
Gecko的对象模型很像微软自带的WebBrowser,Awesomium实在太难啃.