题目分析:将一个数拆成31位,分别用2-sat判断是否符合即可。
代码如下:
#include <map>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std ;
typedef long long LL ;
#pragma comment ( linker , "/STACK:1024000000" )
#define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )
#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define rec( i , A , o ) for ( int i = A[o] ; i != o ; i = A[i] )
#define clr( a , x ) memset ( a , x , sizeof a )
const int MAXN = 505 ;
const int MAXE = 1000005 ;
struct Edge {
int v , n ;
Edge () {}
Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} ;
Edge E[MAXE] ;
int H[MAXN << 1] , cntE ;
int scc[MAXN << 1] , scc_cnt ;
int dfn[MAXN << 1] , low[MAXN << 1] , dfs_clock ;
int S[MAXN << 1] , top ;
int b[MAXN][MAXN] ;
int n ;
void clear () {
top = 0 ;
cntE = 0 ;
scc_cnt = 0 ;
dfs_clock = 0 ;
clr ( H , -1 ) ;
clr ( scc , 0 ) ;
clr ( dfn , 0 ) ;
}
void addedge ( int u , int v ) {
E[cntE] = Edge ( v , H[u] ) ;
H[u] = cntE ++ ;
}
void tarjan ( int u ) {
dfn[u] = low[u] = ++ dfs_clock ;
S[top ++] = u ;
for ( int i = H[u] ; ~i ; i = E[i].n ) {
int v = E[i].v ;
if ( !dfn[v] ) {
tarjan ( v ) ;
low[u] = min ( low[u] , low[v] ) ;
} else if ( !scc[v] ) low[u] = min ( low[u] , dfn[v] ) ;
}
if ( low[u] == dfn[u] ) {
++ scc_cnt ;
do {
scc[S[-- top]] = scc_cnt ;
} while ( u != S[top] ) ;
}
}
bool check () {
rep ( i , 0 , n ) if ( scc[i << 1] == scc[i << 1 | 1] ) return 0 ;
return 1 ;
}
void scanf ( int& x , char c = 0 ) {
while ( ( c = getchar () ) < '0' || c > '9' ) ;
x = c - '0' ;
while ( ( c = getchar () ) >= '0' && c <= '9' ) x = x * 10 + c - '0' ;
}
void solve () {
rep ( i , 0 , n ) rep ( j , 0 , n ) scanf ( b[i][j] ) ;
rep ( i , 0 , 31 ) {
clear () ;
rep ( j , 0 , n ) {
rep ( k , 0 , n ) {
if ( j == k ) continue ;
if ( j % 2 == 1 && k % 2 == 1 ) {
if ( ( b[j][k] >> i ) & 1 ) {
addedge ( j << 1 | 1 , k << 1 ) ;
addedge ( k << 1 | 1 , j << 1 ) ;
} else {
addedge ( j << 1 | 1 , k << 1 | 1 ) ;
addedge ( k << 1 | 1 , j << 1 | 1 ) ;
}
} else if ( j % 2 == 0 && k % 2 == 0 ) {
if ( ( b[j][k] >> i ) & 1 ) {
addedge ( j << 1 , k << 1 ) ;
addedge ( k << 1 , j << 1 ) ;
} else {
addedge ( j << 1 , k << 1 | 1 ) ;
addedge ( k << 1 , j << 1 | 1 ) ;
}
} else {
if ( ( b[j][k] >> i ) & 1 ) {
addedge ( j << 1 , k << 1 | 1 ) ;
addedge ( k << 1 , j << 1 | 1 ) ;
addedge ( j << 1 | 1 , k << 1 ) ;
addedge ( k << 1 | 1 , j << 1 ) ;
} else {
addedge ( j << 1 , k << 1 ) ;
addedge ( k << 1 , j << 1 ) ;
addedge ( j << 1 | 1 , k << 1 | 1 ) ;
addedge ( k << 1 | 1 , j << 1 | 1 ) ;
}
}
}
}
rep ( u , 0 , n ) if ( !dfn[u] ) tarjan ( u ) ;
if ( !check () ) {
printf ( "NO\n" ) ;
return ;
}
}
printf ( "YES\n" ) ;
}
int main () {
while ( ~scanf ( "%d" , &n ) ) solve () ;
return 0 ;
}