@xiaoziyao
2021-08-02T10:55:13.000000Z
字数 2131
阅读 927
解题报告
CF641F Little Artem and 2-SAT解题报告:
给定两个 个点的 2-SAT 模型(各 条限制,型为 ),判断这两个模型的解集是否相同,如果不同,构造一组解使得一个有解一个无解。()
憨憨题+经典题。
这道题告诉我们,2-SAT 不一定一定要用 tarjan 和 kosaraju,有时候 Floyd 也可以在 2-SAT 中有所应用。
事实上,我们用 Floyd 跑一遍传递闭包,然后再 dfs 一遍就可以解出 2-SAT 了。
首先建出来两个 2-SAT 模型,跑一遍,如果两个都无解就相似,如果一个有解一个无解就构造一组使某个模型有解。
否则有一些变量的取值是固定的,判一下是否有固定变量取值不同,或是有一个变量在一个模型确定,一个不确定,很容易构造出解。
此时两个模型的确定变量已经是相同的了,我们比较传递闭包的邻接矩阵是否相同,只要有一个不同的地方(设其为 )且 在另一个模型内均没有确定取值,就可以钦定 ,然后跑一组解就好了。
时间复杂度:。
2-SAT别写错,我写错了调了一个世纪 /ll 。
#include<stdio.h>
#include<bitset>
#define rev(x) (x>n? (x-n):(x+n))
using namespace std;
const int maxn=1005;
int n;
struct two_sat{
int m,ok;
int fixed[maxn<<1];
bitset<maxn<<1>g[maxn<<1];
void get(int x){
fixed[x]=1,fixed[rev(x)]=0;
for(int i=1;i<=2*n;i++)
if(g[x][i]&&fixed[i]==-1)
get(i);
}
void build(){
for(int i=1;i<=2*n;i++)
g[i].reset(),g[i][i]=1,fixed[i]=-1;
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y),x=x>0? x:rev(-x),y=y>0? y:rev(-y);
g[rev(x)][y]=1,g[rev(y)][x]=1;
}
for(int k=1;k<=2*n;k++)
for(int i=1;i<=2*n;i++)
if(g[i][k])
g[i]|=g[k];
for(int i=1;i<=n;i++)
if(g[i][n+i]&&g[n+i][i]){
ok=0;
return ;
}
ok=1;
for(int i=1;i<=n;i++){
if(fixed[i]==-1&&fixed[n+i]==-1&&g[i][n+i])
get(n+i);
if(fixed[i]==-1&&fixed[n+i]==-1&&g[n+i][i])
get(i);
}
}
void solve(){
for(int i=1;i<=2*n;i++)
if(fixed[i]==-1)
get(i);
for(int i=1;i<=n;i++)
printf("%d%c",fixed[i],i==n? '\n':' ');
}
}A,B;
int main(){
scanf("%d%d%d",&n,&A.m,&B.m),A.build(),B.build();
if(A.ok==0&&B.ok==0){
puts("SIMILAR");
return 0;
}
if(A.ok==0||B.ok==0){
if(A.ok)
A.solve();
if(B.ok)
B.solve();
return 0;
}
for(int i=1;i<=2*n;i++){
if(A.fixed[i]!=-1&&B.fixed[i]!=-1&&A.fixed[i]!=B.fixed[i]){
A.solve();
return 0;
}
if((A.fixed[i]==-1)+(B.fixed[i]==-1)==1){
if(A.fixed[i]==-1)
A.get(B.fixed[i]==0? i:rev(i)),A.solve();
if(B.fixed[i]==-1)
B.get(A.fixed[i]==0? i:rev(i)),B.solve();
return 0;
}
}
for(int i=1;i<=2*n;i++)
for(int j=1;j<=2*n;j++){
if(A.g[i][j]&&B.g[i][j]==0&&B.fixed[i]==-1&&B.fixed[i]==-1){
B.get(i),B.get(rev(j)),B.solve();
return 0;
}
if(B.g[i][j]&&A.g[i][j]==0&&A.fixed[i]==-1&&A.fixed[j]==-1){
A.get(i),A.get(rev(j)),A.solve();
return 0;
}
}
puts("SIMILAR");
return 0;
}