2-sat

来源:互联网 发布:知乎 无锡美食 编辑:程序博客网 时间:2024/06/07 17:44

一道2-sat的水题
https://vjudge.net/contest/176902#problem/B

一直不太清楚2-sat是什么,不过貌似已经掌握用dfs判2-sat的方法。

#include<bits/stdc++.h>#define pb push_back #define mp make_pairusing namespace std;const int maxn=1;typedef long long ll;int n,m,ans;int e[58][58],e2[58][58]; int f[58],g[58];void cpy(){    int i,j;    for(i=1;i<=52;++i) g[i]=f[i];    for(i=1;i<=52;++i)      for(j=1;j<=52;++j)        e2[i][j]=e[i][j];}int f2[56];bool dfs(int x){    int i,j,k;    for(i=1;i<=52;++i)    {        if(x!=i&&e2[x][i])        {            if(g[x]==-g[i])            {                if(f2[i]==0)                {                    f2[i]=1;                    if(!dfs(i)) return 0;                }            }            if(g[x]==g[i]) return 0;            if(g[i]==0)             {                g[i]=-g[x];                f2[i]=1;                if(!dfs(i)) return 0;            }        }    }    return 1;}bool check(){    int i,j,k;    memset(f2,0,sizeof(f2));    for(i=1;i<=52;++i)    {        if(!f2[i]&&g[i]!=0)        {            f2[i]=1;            if(!dfs(i))              return 0;        }    }    for(i=1;i<=52;++i)    {        if(!f2[i]&&g[i]==0)        {            f2[i]=1;            g[i]=1;            if(!dfs(i))              return 0;        }    }    /*    for(i=1;i<=52;++i)      for(j=1;j<=52;++j)      {        if(i!=j)        {            if(e2[i][j]&&f2[i]&&f2[j]&&g[i]==g[j]) return 0;        }      }*/    return 1;}int main(){    int i,j,k;    scanf("%d",&n);    for(i=1;i<=n;++i)    {        string t;        cin>>t;        int x=t[0]-'A'+1;        int y=t[1]-'A'+1;        cin>>j>>k;        if(j==2) x+=26,y+=26;        if(k==0)        {            if(f[x]==1||f[y]==1) return 0*printf("0\n");            f[x]=f[y]=-1;        }        else if(k==2)        {            if(f[x]==-1||f[y]==-1) return 0*printf("0\n");            f[x]=f[y]=1;        }        else        {            e[x][y]=e[y][x]=1;        }    }    cpy();    if(!check())    {        return 0*printf("0\n");    }    for(i=1;i<=26;++i)      e[i][i+26]=e[i+26][i]=1;    for(i=1;i<=26;++i)      for(j=i+1;j<=26;++j)        for(k=j+1;k<=26;++k)        {            if(f[i]==1||f[j]==1||f[k]==1||f[i+26]==1||f[j+26]==1||f[k+26]==1) continue;            cpy();            g[i]=-1;            g[j]=-1;            g[k]=-1;            g[i+26]=-1;            g[j+26]=-1;            g[k+26]=-1;            e2[i][i+26]=e2[i+26][i]=0;            e2[j][j+26]=e2[j+26][j]=0;            e2[k][k+26]=e2[k+26][k]=0;            if(check()) ans++;        }    printf("%d\n",ans);    return 0;}
原创粉丝点击