对于2-sat问题的每一个约束:两个条件中至少满足一个;
这里加入满足
x
∣
y
x|y
x∣y,只需要
x
x
x或者
y
y
y满足条件就可以了。
那么如果
x
x
x不满足条件,那么
y
y
y必须满足条件;反之亦然;
那么就可以对于这种约束条件建边在
x
x
x不满足条件的情况下,
y
y
y必须满足条件,即
!
x
−
>
y
!x->y
!x−>y;同理可以知道
!
y
−
>
x
!y->x
!y−>x;
这个建边方式可以推广到一般的约束中去,只要是2-sat,即两者之间的约束都可以(约束关系只在x,y之间)。
这样的话,对于图中的联通块,必须同时满足条件,然后可以随便构造出一组解就可以了。对于所在的联通块,有个拓扑关系。只需要所有的拓扑关系都统一构造方式(我一般用ring[x]<ring[x+n]的x为1),就可以得到唯一解;
如果x=0和x=1在一个联通块中,就不满足条件;
这里附上代码:
void dfs(int u){
dfn[u]=low[u]=++cnt;
st[++top]=u;
For(i,0,G[u].size()-1){
int v=G[u][i];
if(!dfn[v]){
dfs(v);
low[u]=min(low[u],low[v]);
}
else if(!ring[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
int v;
++tot;
do{
v=st[top--];
ring[v]=tot;
}while(u!=v);
}
}
For(i,1,m){
int x,a,y,b;
scanf("%d%d%d%d",&x,&a,&y,&b);//x 0|1 y 0|1
G[x+(a&1)*n].push_back(y+(b^1)*n);
G[y+(b&1)*n].push_back(x+(a^1)*n);
}
For(i,1,n<<1) if(!dfn[i]) dfs(i);