[2-SAT 构造] Codeforces Gym 101173 CERC 16 L. Lost Logic

题目大意 给 n <script type="math/tex" id="MathJax-Element-115">n</script>个01变量的三种取值 构造形如 (!)a->(!)b 的限制 使得有且仅有这三个满足
首先我们可以把三个值一样的变量去掉 只要一个限制就够了
然后剩下6类 类内部的变量一定两两相同 那么加一下限制
完全互补的两类可以合并 只要分别取出代表 限制两个一定相反就好了
这样我们最多剩下三类

  • 一类 显然不需要限制
  • 两类 去两个代表 这两个变量的值组成的二元组只有三种值是有效的 实际上总共有四种值 只要加一个限制就可以去掉第四种
  • 三类 无解
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<string>
#include<sstream>
#include<vector>
#define pb push_back
using namespace std;

const int N=55;

int n,a[N];
#define read(x) scanf("%d",&(x))

inline string itos(int i){ 
  stringstream s;  s<<i; return s.str();
} 
inline string identifier(bool nneg,int x){
  return string(!nneg?"!":"")+"x"+itos(x);
}


string ans;
int tot;
inline void imp(bool negx,int x,bool negy, int y){
  tot++,ans+=identifier(negx,x)+" -> "+identifier(negy,y)+"\n";
}

vector<int> v[8];
vector<int> _v;
int w[8];

int main(){
  int x;
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(n);
  for (int j=0;j<3;j++)
    for (int i=1;i<=n;i++)
      read(x),a[i]=(a[i]<<1)|x;
  for (int i=1;i<=n;i++)
    if (a[i]==0)
      imp(1,i,0,i);
    else if (a[i]==7)
      imp(0,i,1,i);
    else if (__builtin_popcount(a[i])==1)
      v[a[i]].pb(i);
    else
      v[~a[i]&7].pb(i);
  for (int i=0;i<8;i++)
    if (__builtin_popcount(i)==1){
      if (v[i].size()) _v.pb(i);
      for (int j=1;j<(int)v[i].size();j++)
    if (a[v[i][0]]^a[v[i][j]])
      imp(0,v[i][0],1,v[i][j]),imp(1,v[i][0],0,v[i][j]);
    else
      imp(0,v[i][0],0,v[i][j]),imp(1,v[i][0],1,v[i][j]);
    }
  if (_v.size()==3) return printf("-1\n"),0;
  for (int i=0;i<3;i++) w[1<<i]=i;
  int v0=_v[0],v1=_v[1];
  imp((a[v[v0][0]]>>w[v0])&1,v[v0][0],(a[v[v1][0]]>>w[v0])&1,v[v1][0]);
  printf("%d\n%s\n",(int)tot,ans.c_str());
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值