题目链接
经典的2-SAT问题,每个位都执行一次,把所有不满足条件的条件加入
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll;
const int maxn = 700 + 5 ;
struct TwoSAT {
int n;
vector <int > G[maxn*2 ];
bool mark[maxn*2 ];
int S[maxn*2 ], c;
bool dfs(int x) {
if (mark[x^1 ]) return false ;
if (mark[x]) return true ;
mark[x] = true ;
S[c++] = x;
for (int i = 0 ; i < G[x].size(); i++)
if (!dfs(G[x][i])) return false ;
return true ;
}
void init(int n) {
this ->n = n;
for (int i = 0 ; i < n*2 ; i++) G[i].clear();
memset (mark, 0 , sizeof (mark));
}
void add_clause(int x, int xval, int y, int yval) {
x = x * 2 + xval;
y = y * 2 + yval;
G[x^1 ].push_back(y);
G[y^1 ].push_back(x);
}
bool solve() {
for (int i = 0 ; i < n*2 ; i += 2 )
if (!mark[i] && !mark[i+1 ]) {
c = 0 ;
if (!dfs(i)) {
while (c > 0 ) mark[S[--c]] = false ;
if (!dfs(i+1 )) return false ;
}
}
return true ;
}
};
TwoSAT solver;
int n,m;
int b[maxn][maxn];
int a[maxn][maxn][50 ];
int main()
{
ios_base::sync_with_stdio(false );
while (cin >> n)
{
int maxd=0 ;
memset (a,0 ,sizeof (a));
memset (b,0 ,sizeof (b));
int f=1 ;
for (int i=0 ;i<n;i++)
{
for (int j=0 ;j<n;j++)
{
cin >> b[i][j];
if (i==j&&b[i][j]!=0 )
f=0 ;
int t = b[i][j];
int dig = 0 ;
while (t)
{
a[i][j][dig++] = t&1 ;
t>>=1 ;
}
maxd = max(maxd,dig);
}
}
for (int i=0 ;i<n&&f;i++)
{
for (int j=0 ;j<n&&f;j++)
{
if (b[i][j]!=b[j][i])
{
f=0 ;
}
}
}
for (int ndig=0 ;ndig<maxd&&f;ndig++)
{
solver.init(n+5 );
for (int i = 0 ; i < n&&f; ++i)
{
for (int j = 0 ; j < i&&f; ++j)
{
if (i==j) continue ;
int op=a[i][j][ndig];
int u,v;
if ((i&1 )&&(j&1 ))
{
for (u=0 ;u<2 ;u++)
for (v=0 ;v<2 ;v++)
if ((u|v)!=op)
solver.add_clause(i,u,j,v);
}
else if (!(i&1 )&&!(j&1 ))
{
for (u=0 ;u<2 ;u++)
for (v=0 ;v<2 ;v++)
if ((u&v)!=op)
solver.add_clause(i,u,j,v);
}
else
{
for (u=0 ;u<2 ;u++)
for (v=0 ;v<2 ;v++)
if ((u^v)!=op)
solver.add_clause(i,u,j,v);
}
}
}
if (!solver.solve())
{
f=0 ;
break ;
}
}
if (f==1 )
{
cout <<"YES" <<endl;
}
else
{
cout <<"NO" <<endl;
}
}
return 0 ;
}