Bit Magic
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2057 Accepted Submission(s): 590
Problem Description
Yesterday, my teacher taught me about bit operators: and (&), or (|), xor (^). I generated a number table a[N], and wrote a program to calculate the matrix table b[N][N] using three kinds of bit operator. I thought my achievement would get teacher‘s attention.
The key function is the code showed below.
There is no doubt that my teacher raised lots of interests in my work and was surprised to my talented programming skills. After deeply thinking, he came up with another problem: if we have the matrix table b[N][N] at first, can you check whether corresponding number table a[N] exists?
Input
There are multiple test cases.
For each test case, the first line contains an integer N, indicating the size of the matrix. (1 <= N <= 500).
The next N lines, each line contains N integers, the jth integer in ith line indicating the element b[i][j] of matrix. (0 <= b[i][j] <= 2 31 - 1)
Output
For each test case, output "YES" if corresponding number table a[N] exists; otherwise output "NO".
Sample Input
2
0 4
4 0
3
0 1 24
1 0 86
24 86 0
Sample Output
YES
NO
Source
2012 Asia ChangChun Regional Contest
two-sat ,果然考的就是构图 。。。
那些边的数量不好估计空间大小, 所以还是用stl 来构边好了 。 。
然后对于 two-sat .. 特别喜欢构反向边 ..不知道这个是不是好习惯。 。
讲回这题。 。
分3种运算,
1 。 | (或运算符) ....
a. 若 b[i][j] 的二进制第大k位为 0 的时候 , a[i] , a[j]只能为 0 了 。
b. 否则 , a[i] , a[j]不能同为 0 。
2 。 & (与运算符) ...
a. 若 b[i][j] 的二进制第大k位为 1 的时候 , a[i] , a[j]只能为 1 了 。
b. 否则 , a[i] , a[j]不能同为 1 。
3。 ^(异或运算符)...
a. 若 b[i][j] 的二进制第大k位为 0 的时候 , a[i] , a[j]只能相同 了 。
b. 否则 , a[i] , a[j] 不能相同。
按照上面的规则构图就行了 。。
然后再进行two-sat的时候 , 要对B数组先检测一下
是否符合 1.( i == j && B[i][j] == 0 )
2.( i != j && B[i][j] == B[j][i] )
一开始构图构蒙了,连这个也没判。 值得WA了 。
最后 , 就是对二进制位, 每一个位(位与位之间不存在关系)判一次 two-sat
一开始 ,全部弄一起判,边所用的空间太恐怖了 ~~MLE 了
#include <cstdio> #include <algorithm> #include <cstring> #include <iostream> #include <vector> using namespace std; const int N = 550 ; int n ; int B[N][N]; vector<int>g[N<<1]; int st[N<<2] , top ; bool mark[N<<2]; void init() { for( int i = 0; i < 2 * n ; ++i ) g[i].clear(); memset( mark ,false, sizeof mark ); } void addedge( int u , int v ) { g[u].push_back(v) , g[v].push_back(u); } bool dfs( int u ) { if( mark[u] ) return true; if( mark[u^1] ) return false; mark[u] = true; st[ top++ ] = u ; for( int i = 0 ; i < g[u].size(); ++i ){ int v = g[u][i]; if( !dfs( v^1 ) ) return false; } return true; } bool solve() { for( int i = 0 ; i < 2 * n ; i += 2 ){ if( !mark[i] && !mark[i+1] ){ top = 0 ; if( !dfs(i) ){ while( top > 0 ) mark[ st[--top] ] = false; if( !dfs( i+1 ) ) return false; } } } return true; } bool check() { for( int i = 0 ; i< n ; ++i ){ for( int j = i ; j < n ; ++j ){ if( i == j && B[i][j] != 0 )return false ; else if( i != j && B[i][j] != B[j][i] ) return false; } } return true; } void run() { for( int i = 0 ; i < n ; ++i ){ for( int j = 0 ; j < n ; ++j ){ scanf("%d",&B[i][j]); } } if( !check() ) { puts("NO"); return ; } for( int k = 0 ; k < 31 ; ++k ){ init(); for( int i = 0 ; i < n ; ++i ){ for( int j = i + 1 ; j < n ; ++j ){ if( ( i % 2 == 1 ) && ( j % 2 == 1 ) ){ // | if( ( B[i][j]&(1<<k) ) ){ addedge( 2*i^1 ,2*j^1 ); } else{ addedge( 2*i ,2*j^1 ); addedge( 2*i ,2*j ); addedge( 2*i^1 , 2*j ); } } else if( ( i % 2 == 0 )&& ( j % 2 == 0 ) ) { // & if( ( B[i][j]&(1<<k)) == 0 ){ addedge( 2*i ,2*j ); } else { addedge( 2*i^1 ,2*j^1 ); addedge( 2*i^1 ,2*j ); addedge( 2*i , 2*j^1 ); } } else { // ^ if( ( B[i][j] & ( 1<< k) ) != 0 ){ addedge( 2*i ,2*j ); addedge( 2*i^1 ,2*j^1 ); } else { addedge( 2*i^1 ,2*j ); addedge( 2*i,2*j^1 ); } } } } if( !solve() ) { puts("NO"); return ; } } puts("YES"); } int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif // LOCAL while( ~scanf("%d",&n) ) run(); }