一道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_pair
using 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;
}