bzoj4945

题解:

一眼看过去还以为是3-sat

其实d只有8

那么我们可以枚举每一个x选择哪一个

然后再用2-sat处理

代码:

#include<bits/stdc++.h> 
using namespace std;
const int N=100005,M=N<<6,ABC='A'+'B'+'C';
struct Edge{int to,next;}e[M];
int n,m,K,pos[10],zz[M],ne[M],mi[N],mj[N],fi[N<<1],len,st[N],cot;
char Str[N],hi[N],hj[N];bool Mark[N<<1],Un[N<<1];
void jb(int x,int y)
{
    zz[++len]=y;ne[len]=fi[x];fi[x]=len;
    zz[++len]=x^1;ne[len]=fi[y^1],fi[y^1]=len;
}
int dfs(int x)
{
    if (Mark[x^1]||(n>10000&&Un[x]))return 0;
    if (Mark[x])return 1;
    Mark[x]=1;st[++cot]=x;
    for (int i=fi[x];i;i=ne[i])
     if (!dfs(zz[i]))
      {
          Un[x]=1;
        return 0;
      }
    return 1;    
}
void init()
{
    memset(fi,0,sizeof fi);
    memset(Mark,0,sizeof Mark);
    memset(Un,0,sizeof Un);
}
int pd()
{
    len=1;int n1,n2;
    init();
    for (int i=1;i<=m;i++)
     {
        if (hi[i]==Str[mi[i]])continue;
        n1=hi[i]>ABC-hi[i]-Str[mi[i]];
        if (hj[i]==Str[mj[i]])jb(mi[i]<<1|n1,mi[i]<<1|n1^1);
        else n2=hj[i]>ABC-hj[i]-Str[mj[i]],jb(mi[i]<<1|n1,mj[i]<<1|n2);
     }
    for (int i=1;i<=n;i++)
     {
        cot=0;
        if (!dfs(i<<1))
         {
            while (cot)Mark[st[cot--]]=0;
            if (!dfs(i<<1|1))return 0;
         }
     }
    for (int i=1;i<=n;i++)
     if (Mark[i<<1])putchar(Str[i]=='A'?'B':'A');
     else putchar(Str[i]=='C'?'B':'C');
    return 1;
}
int main()
{
    scanf("%d%d%s%d",&n,&K,Str+1,&m);
    int cnt=0;
    for (int i=1;i<=m;i++)scanf("%d%s%d%s",&mi[i],&hi[i],&mj[i],&hj[i]);
    for (int i=1;i<=n;i++)
     if (Str[i]=='x')pos[cnt++]=i;else Str[i]+='A'-'a';
    for (int i=0;i<1<<K;i++)
     {
        for (int j=0;j<K;j++)Str[pos[j]]='A'+(i>>j&1);
        if (pd())return 0;
     }
    puts("-1");
    return 0;
}
原文地址:https://www.cnblogs.com/xuanyiming/p/8166112.html