题意
给出两个2-sat,如果存在使其中一组成立,另一组不成立的变量取值,输出之,否则输出SIMILAR
题解
按照2-sat的正常操作建边
我们可以跑一发floyd
注意一定要连一个自己到自己的边
(前来更新,根据某dalao指出https://blog.csdn.net/qq_34454069,其实可以不用,后面判断的时候看一下i、j相不相等就可以了)
然而,有的时候,某个变量会有特定的取值(真或假),(例如有从i到!i的路径)此时我们就需要连边来保证,否则可能会出现两个2-sat都保证该变量的取值,却连边不同的情况,进而影响我们最终出解
然后呢,对于这两个2-sat所得到的邻接矩阵,如果存在路径u->v存在于有且只有一个矩阵中(不妨设为存在于f中不存在于g中)
那么我们令u=1,v=0,那么f就为假,g就为真
就达成了目标
如果不存在,那么输出SIMILAR
分析时间复杂度,主要体现在floyd处,
O((2⋅N)3)=O(8⋅N3)
O
(
(
2
·
N
)
3
)
=
O
(
8
·
N
3
)
,N是1000,所以会TLE
然而我们有神器bitset,复杂度除以32,就可以过了。(时间限制3s)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<bitset>
#include<string>
#include<iostream>
using namespace std;
const int N=2010;
int n;
int ans[N];
void watch(bitset<N> a){
string s=a.to_string();
reverse(s.begin(),s.end());
cout<<s<<endl;
}
struct _2sat{
bitset<N> g[N];//表示推出关系
int m;
void debug(){
for(int i=0;i<2*n;i++)
watch(g[i]);
}
int get(int x){
if(x>0)
return x*2-2;//如果是正数,返回一个偶数值
else
return -x*2-1;//如果是负数,返回一个奇数值
}
void read(){
while(m--){
int x,y;
scanf("%d%d",&x,&y);
x=get(x),y=get(y);//连边
g[x^1].set(y);
g[y^1].set(x);
//debug();
}
//debug();
}
void calc(){//本质上等同一个floyd
//debug();
for(int i=0;i<2*n;i++)
for(int j=0;j<2*n;j++)
if(g[j][i])
g[j]|=g[i];
//debug();
}
void solve(){
calc();
for(int i=0;i<n*2;i++)
if(g[i][i^1]){//如果存在着i->!i,则不能选择i
for(int j=0;j<n*2;j++){
g[i].set(j);
g[j].set(i^1);
}
}
calc();
}
void dfs(int v){//通过推出关系找出答案
if(ans[v]!=-1)
return ;
ans[v]=1,ans[v^1]=0;
for(int i=0;i<n*2;i++)
if(g[v][i])
ans[i]=1,ans[i^1]=0;
}
void getans(int u,int v){//由于有一个包含u->v,另一个没有,那么我们就令u为1,v为0,就可满足题意
dfs(u);
dfs(v^1);
for(int i=0;i<n*2;i++)//其他的就随便令值
if(ans[i]==-1&&!g[i][i^1])
dfs(i);
}
}F,G;
int main()
{
scanf("%d%d%d",&n,&F.m,&G.m);
F.read(),F.solve();
G.read(),G.solve();
//F.debug(),G.debug();
memset(ans,-1,sizeof ans);
for(int i=0;i<n*2;i++)
{
for(int j=0;j<n*2;j++)
{
if (i!=j&&F.g[i][j]!=G.g[i][j])
{
if (F.g[i][j])
G.getans(i,j);
else
F.getans(i,j);
for(int k=0;k<n;k++)
printf("%d ",ans[k*2]);//偶数中储存的是该变量对应的答案
puts("");
return 0;
}
}
}
puts("SIMILAR");
}