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

来源:互联网 发布:淘宝代运营公司 编辑:程序博客网 时间:2024/06/06 01:43

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

  • 一类 显然不需要限制
  • 两类 去两个代表 这两个变量的值组成的二元组只有三种值是有效的 实际上总共有四种值 只要加一个限制就可以去掉第四种
  • 三类 无解
#include<cstdio>#include<cstdlib>#include<algorithm>#include<string>#include<sstream>#include<vector>#define pb push_backusing 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
原创粉丝点击