@description@

给定两个 2-sat 问题,询问两个问题的解集是否相同。

如果不相同,构造一组解 {xi},使得这个解是其中一个问题的解同时不是另一个问题的解。

原题链接。

@solution@

如果两者解集都为空,那么解集相同。

如果两者只有一个解集为空,则取另一个问题的任意解即可。

如果都有解,先跑个 bitset 优化的传递闭包,方便接下来的处理。

此时有一些变量的值是确定的(即可以从该变量的 0/1 状态到达该变量的 1/0 状态)。

如果有一个变量在问题 A 中确定而在问题 B 中不确定,则强制令 B 中该变量的值为 A 中值取反,暴力求此时 B 中的任意解。

如果有一个变量在两个问题中都确定但是确定的值不同,直接取问题 A 的任意解即可。

现在确定的变量都长一样了。但是不确定的变量可能相互制约,所以还是不能断定两个问题解集相同。

如果两个不确定的变量对应的结点 u, v,在问题 A 中有边相连 u -> v,在问题 B 中没有边相连,我们就可以构造出一组解。

在问题 B 中强制令 u 为真,v 为假,构造出 B 的任意解,该解在 A 中一定不成立。

@accepted code@

#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std; const int MAXN = 2000; bitset<MAXN>G[2][MAXN]; int n; int abs(int x) {return x >= 0 ? x : -x;} bool f[2]; int a[2][MAXN + 5];
void get(int o) {
for(int i=0;i<n;i++) {
if( a[o][i] == -1 ) {
for(int j=0;j<n;j++)
if( (a[o][j] == 0 && G[o][i<<1|1][j<<1|1]) || (a[o][j] == 1 && G[o][i<<1|1][j<<1]) ) {
a[o][i] = 0;
break;
}
if( a[o][i] == -1 ) a[o][i] = 1;
}
printf("%d ", a[o][i]);
}
exit(0);
} int main() {
int m[2]; scanf("%d%d%d", &n, &m[0], &m[1]);
for(int o=0;o<2;o++) {
for(int i=1;i<=m[o];i++) {
int a, b; scanf("%d%d", &a, &b);
int p = (a < 0), q = (b < 0); a = abs(a) - 1, b = abs(b) - 1;
G[o][a<<1|p][b<<1|(!q)] = true, G[o][b<<1|q][a<<1|(!p)] = true;
}
for(int i=0;i<(n<<1);i++) G[o][i][i] = true;
for(int k=0;k<(n<<1);k++)
for(int i=0;i<(n<<1);i++)
if( G[o][i][k] ) G[o][i] |= G[o][k];
for(int i=0;i<n;i++) {
if( G[o][i<<1][i<<1|1] && G[o][i<<1|1][i<<1] ) {
f[o] = true;
break;
}
else if( G[o][i<<1][i<<1|1] ) a[o][i] = 1;
else if( G[o][i<<1|1][i<<1] ) a[o][i] = 0;
else a[o][i] = -1;
}
}
if( f[0] && f[1] ) puts("SIMILAR");
else if( f[0] ) get(1);
else if( f[1] ) get(0);
else {
for(int i=0;i<n;i++)
if( a[0][i] != a[1][i] ) {
if( a[0][i] == -1 ) a[0][i] = (!a[1][i]), get(0);
else if( a[1][i] == -1 ) a[1][i] = (!a[0][i]), get(1);
else get(0);
return 0;
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++) {
if( a[0][i] == -1 && a[0][j] == -1 ) {
if( G[0][i<<1|1][j<<1|1] != G[1][i<<1|1][j<<1|1] ) {
if( G[0][i<<1|1][j<<1|1] == 0 )
a[0][i] = 1, a[0][j] = 0, get(0);
else a[1][i] = 1, a[1][j] = 0, get(1);
return 0;
}
else if( G[0][i<<1|1][j<<1] != G[1][i<<1|1][j<<1] ) {
if( G[0][i<<1|1][j<<1] == 0 )
a[0][i] = 1, a[0][j] = 1, get(0);
else a[1][i] = 1, a[1][j] = 1, get(1);
return 0;
}
else if( G[0][i<<1][j<<1|1] != G[1][i<<1][j<<1|1] ) {
if( G[0][i<<1][j<<1|1] == 0 )
a[0][i] = 0, a[0][j] = 0, get(0);
else a[1][i] = 0, a[1][j] = 0, get(1);
return 0;
}
else if( G[0][i<<1][j<<1] != G[1][i<<1][j<<1] ) {
if( G[0][i<<1][j<<1] == 0 )
a[0][i] = 0, a[0][j] = 1, get(0);
else a[1][i] = 0, a[1][j] = 1, get(1);
return 0;
}
}
}
puts("SIMILAR");
}
}

@details@

注意有一些边界情况,预先给每个结点连个自环。

@codeforces - 668E@ Little Artem and 2-SAT的更多相关文章

  1. Codeforces 669D Little Artem and Dance (胡搞 + 脑洞)

    题目链接: Codeforces 669D Little Artem and Dance 题目描述: 给一个从1到n的连续序列,有两种操作: 1:序列整体向后移动x个位置, 2:序列中相邻的奇偶位置互 ...

  2. codeforces 442C C. Artem and Array(贪心)

    题目链接: C. Artem and Array time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  3. CodeForces - 669D Little Artem and Dance 想法题 多余操作

    http://codeforces.com/problemset/problem/669/D 题意:n个数1~N围成一个圈.q个操作包括操作1:输入x, 所有数右移x.操作2:1,2位置上的数(swa ...

  4. CodeForces 668B Little Artem and Dance

    B. Little Artem and Dance time limit per test 2 second memory limit per test 256 megabytes input sta ...

  5. codeforces 668C - Little Artem and Random Variable

    题目链接:http://codeforces.com/contest/668/problem/C --------------------------------------------------- ...

  6. codeforces 442C C. Artem and Array(有深度的模拟)

    题目 感谢JLGG的指导! 思路: //把数据转换成一条折线,发现有凸有凹 //有凹点,去掉并加上两边的最小值//无凹点,直接加上前(n-2)个的和(升序)//数据太大,要64位//判断凹与否,若一边 ...

  7. CodeForces 669E Little Artem and Time Machine

    树状数组,$map$. 可以理解为开一个数组$f[i][j]$记录:$i$这个数字在时间$j$的操作情况. 操作$1$:$f[x][t]++$.操作$2$:$f[x][t]--$.操作$3$:$f[x ...

  8. CodeForces 669D Little Artem and Dance

    模拟. 每个奇数走的步长都是一样的,每个偶数走的步长也是一样的. 记$num1$表示奇数走的步数,$num2$表示偶数走的步数.每次操作更新一下$num1$,$num2$.最后输出. #pragma ...

  9. CodeForces 669C Little Artem and Matrix GNU

    模拟. 把操作记录一下,倒着复原回去. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cs ...

随机推荐

  1. 为什么我不建议你通过 Python 去找工作?

    二哥,你好,我是一名大专生,学校把 Python 做为主语言教给我们,但是我也去了解过,其实 Python 门槛挺高的,所以我在自学 Java,但是我现在并不清楚到底要不要全心的去学 Java,学校里 ...

  2. 实验6、Python-OpenCV宽度测量

    一. 题目描述 测量所给图片的高度,即上下边缘间的距离. 思路: 将图片进行阈值操作得到二值化图片. 截取只包含上下边框的部分,以便于后续的轮廓提取 轮廓检测 得到结果 二. 实现过程 1.用于给图片 ...

  3. zepto快速入门教程

    * zepto* 特点:1.体积8kb2.针对移动端的框架3.语法同jquery大部分一样,都是$为核心函数4.目前功能完善的框架体积最小的左右* 同jquery相似的语法核心:$--作为函数使用参数 ...

  4. Unity中激活子物体

    void GetChildrenAndSetActive() { Transform[] imageTargetObjects = GetComponentsInChildren<Transfo ...

  5. [工具推荐]004.EXE签名工具SignTool使用教程

    数字证书,真是个神奇的东西,可以保证软件不被修改,可以表明文件的发布日期,最重要的,可以很大程度的减少杀毒软件的误报,当然,这就要使用可信任的机构颁发的证书了. 现在要说的不是申请证书,而是如何制作自 ...

  6. Spring_使用JdbcTemplate和JdbcDaoSupport

    1.JdbcTemplate 简化 JDBC 模板查询 ①每次使用都创建一个 JdbcTemplate 的新实例, 这种做法效率很低下.②JdbcTemplate 类被设计成为线程安全的, 所以可以再 ...

  7. 逃离CSDN

    2012年2月18日,从CSDN搬家到这里.对于搬家的理由,总觉得该说点什么.我是在2012年1月29日又开始写博客的,在此之前我的CSDN博客闲置了10个月.从1月29日开始,不到1个月的时间建立了 ...

  8. Apache Hudi在医疗大数据中的应用

    本篇文章主要介绍Hudi在医疗大数据中的应用,主要分为5个部分进行介绍:1. 建设背景,2. 为什么选择Hudi,3. Hudi数据同步,4. 存储类型选择及查询优化,5. 未来发展与思考. 1. 建 ...

  9. java1.8时间处理

    object TimeUtil { var DEFAULT_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss") var H ...

  10. Java实现 LeetCode 790 多米诺和托米诺平铺(递推)

    790. 多米诺和托米诺平铺 有两种形状的瓷砖:一种是 2x1 的多米诺形,另一种是形如 "L" 的托米诺形.两种形状都可以旋转. XX <- 多米诺 XX <- &q ...