It seems that the great gods use 2-Sat, but I have also thought about it. Because I have encountered several questions that determine YES or NO (2-Sat, query set, search, and game, so I encountered these kinds of problems. It seems that I still need to do more health check and accumulate experience in the future :)), but I still used and checked the set during the competition. below is my method of checking the set:
Split each bit in the B [] [] array into two vertices I and I '(no more than 32 bits), and add two new vertices 0 and 1, if it is determined that a vertex I corresponds to 0, the vertex I is merged with 0, and the vertex I is merged with 1. If it is determined that a vertex I corresponds to 1, merge I and 1, and merge I 'and 0. If the bits corresponding to two points I and J are determined to be the opposite number, merge I and j, and merge J and I; if the number of BITs corresponding to the two points is determined to be the same, merge I and j, and merge I and j.
I have been busy recently, so I have a lot of questions, so let's take a look at the code.
Because I want to leave the number blank to 0 and 1, so I am from 1 to n instead of from 0 to n-1, so the parity judgment should be changed.
# Include <cstdio> # include <cstring> # include <iostream> # include <algorithm> using namespace STD; const int maxn = 100000; int P [maxn]; int B [505] [505]; int N; void Init () {for (INT I = 0; I <(2 * n + 1) * 32 + 100; I ++) P [I] = I;} int find (INT X) {return x = P [x]? X: P [x] = find (P [x]);} void Union (int x, int y) {int A = find (x ), B = find (y); P [a] = P [B] = P [x] = P [y] = min (a, B);} bool check () {for (INT I = 1; I <= N; I ++) {for (Int J = I + 1; j <= N; j ++) if (B [I] [J]! = B [J] [I]) return 0; If (B [I] [I]! = 0) return 0;} Init (); int M = 32 * n; For (INT I = 1; I <= N; I ++) for (Int J = I + 1; j <= N; j ++) {if (I % 2 = 0 & J % 2 = 0) {for (int K = 0; k <32; k ++) {If (B [I] [J] & (1 <K) = 0) {int u = I * 32 + k, V = J * 32 + k; If (find (u) = find (1) | find (V) = find (1) | find (u) = find (V + M) return 0; Union (u, 0); Union (v, 0 ); union (U + M, 1); Union (V + M, 1) ;}} else if (I % 2 = 1 & J % 2 = 1) {for (int K = 0; k <32; k ++) {If (B [I] [J] & (1 <k) {int u = I * 32 + k, V = J * 32 + k; If (find (u) = find (0) | find (v) = find (0) | find (u) = find (V + M) return 0; Union (u, 1); Union (V, 1); Union (U + M, 0); Union (V + M, 0) ;}} else {for (int K = 0; k <32; k ++) {int u = I * 32 + k, V = J * 32 + K; if (B [I] [J] & (1 <k) {If (find (u) = find (V) return 0; Union (u, V + M); Union (U + M, V);} else {If (find (u) = find (V + M) return 0; Union (u, v); Union (U + M, V + M) ;}}} return 1 ;}int main () {While (~ Scanf ("% d", & N) {for (INT I = 1; I <= N; I ++) for (Int J = 1; j <= N; j ++) scanf ("% d", & B [I] [J]); If (check () puts ("yes "); else puts ("no");} return 0 ;}
2012 Changchun Site B Question zoj 3656