首页 > 其他 > 详细

2-SAT 学习笔记

时间:2020-01-30 22:37:37      阅读:84      评论:0      收藏:0      [点我收藏+]

对于一个命题:如果a,那么b
其逆命题为:如果b,那么a
其否命题为:如果?a,那么?b
其逆否命题为:如果?b,那么?a
∧表示与,∨表示或,?表示非
原命题与逆否命题等值。逆命题与否命题等值
原命题与逆命题以及逆否命题与否命题之间没有关系

那么只需要 \(a -> b\) \(!b -> !a\) 就可以了

2-SAT板子

考虑 \(x_i\) 只有两个状态
此题说的是两者满足其一
那么可以转化成 满足前者且不满足后者 的关系
所以就这样了。

#include<bits/stdc++.h>
using namespace std ;
int n , m ;
const int N = 1e6 + 10 ;
struct node { int v , nxt ; } e[N << 1] ;
int head[N << 1] , cnt = 0 ;
inline void add(int u , int v) {
  e[++ cnt] = { v , head[u] } ;
  head[u] = cnt ;
}
int dfn[N << 1] , low[N << 1] , idx = 0 ;
int st[N << 1] , tp = 0 ;
int co[N << 1] , num = 0 ;
inline void tarjan(int u) {
  dfn[u] = low[u] = ++ idx;
  st[++ tp] = u;
  for(register int i = head[u]; i; i = e[i].nxt) {
    int v = e[i].v;
    if(! dfn[v]) {
      tarjan(v) ;
      low[u] = min(low[u] , low[v]) ;
    }
    else if(! co[v]){
      low[u] = min(low[u] , dfn[v]) ;
    }
  }
  if(low[u] == dfn[u]) {
    co[u] = ++ num ;
    while(st[tp] ^ u) {
      co[st[tp --]] = num ;
    } tp -- ;
  }
}

signed main() {
#ifdef _WIN64
  freopen("0.in" , "r" , stdin) ;
#endif
  ios :: sync_with_stdio(false) ;
  cin.tie(nullptr) ;
  cout.tie(nullptr) ;
  cin >> n >> m ;
  for(register int i = 1 ; i <= m ; i ++) {
    int a , f , b , f2 ;
    cin >> a >> f >> b >> f2 ;
    add(a + n * (f ^ 1) , b + n * (f2 & 1)) ;
    add(b + n * (f2 ^ 1) , a + n * (f & 1)) ;
  }
  for(register int i = 1 ; i <= (n << 1) ; i ++)
    if(! dfn[i]) tarjan(i) ;
  for(register int i = 1 ; i <= n ; i ++)
    if(co[i] == co[n + i]) { puts("IMPOSSIBLE") ; return 0 ; }
  cout << "POSSIBLE\n" ;
  for(register int i = 1 ; i <= n ; i ++) {
    if(co[i] > co[i + n]) cout << 1 << ' ' ;
    else cout << 0 << ' ' ;
  }
  return 0 ;
}

2-SAT 学习笔记

原文:https://www.cnblogs.com/Isaunoya/p/12244119.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!