【题意】
给定n个数a0,,,an-1,它按照以下方式生成b[][]:
现给定b[][],求A是否存在。
【分析】
1、只涉及位运算,可对每一个二进制位考虑。
2、对某个二进制位,ai的值要么为0,要么为1。再根据bij的值,找出ai和aj的关系。做一个2-sat可解。
【建图】
1、建图详见代码。注意如果第i个数必须为0,加边(i1->i0)。
2、tarjan缩点求解。
【Mark】
注意原数组坐标从0开始,WA 1发。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <ctime> 6 #include <cassert> 7 #include <iostream> 8 #include <sstream> 9 #include <fstream> 10 #include <map> 11 #include <set> 12 #include <vector> 13 #include <queue> 14 #include <algorithm> 15 #include <iomanip> 16 using namespace std; 17 18 #define abs(x) ((x)>=0?(x):-(x)) 19 #define i64 long long 20 #define u32 unsigned int 21 #define u64 unsigned long long 22 #define clr(x,y) memset(x,y,sizeof(x)) 23 #define PI acos(-1.0) 24 #define sqr(x) ((x)*(x)) 25 #define maxn 2005 26 #define maxm 2000005 27 struct node 28 { 29 int v,next; 30 }; 31 node e[maxm]; 32 int cnt ; 33 int head[maxn]; 34 int col[maxn]; 35 bool instack[maxn]; 36 int st[maxn],top; 37 int scnt; 38 int dep; 39 int dfn[maxn],low[maxn]; 40 void init() 41 { 42 cnt = 0; 43 memset(head,-1,sizeof(head)); 44 return ; 45 } 46 void add(int u ,int v ) 47 { 48 e[cnt].v = v ; 49 e[cnt].next = head[u]; 50 head[u] = cnt ++ ; 51 } 52 int n ; 53 void tarjan(int u) 54 { 55 int v,x; 56 dfn[u] = low[u] = cnt ++ ; 57 st[++top] = u; 58 instack[u] = 1 ; 59 for(int i = head[u] ; i!= -1; i = e[i].next) 60 { 61 v = e[i].v; 62 if(dfn[v] == -1) 63 { 64 tarjan(v); 65 low[u] = min(low[u],low[v]); 66 } 67 else if(instack[v] ) low[u] = min(low[u],dfn[v]); 68 } 69 if(dfn[u] == low[u] ) 70 { 71 do 72 { 73 x = st[top -- ]; 74 instack[x] = 0; 75 col[x] = scnt; 76 }while(x != u); 77 scnt ++ ; 78 } 79 } 80 int b[505][505]; 81 bool work(int k) 82 { 83 int val ; 84 // build graph 85 init(); 86 for(int i = 1 ;i <= n ; i ++ ) 87 { 88 for(int j = 1 ;j <= n ; j ++ ) 89 { 90 if(i == j) 91 { 92 if(b[i][j] != 0 ) return false; 93 } 94 else 95 { 96 val = (b[i][j] >> k ) & 1 ; 97 if(i % 2 == 0 && j %2 == 0 ) 98 { 99 if(val == 0 ) 100 { 101 add(i+n,i); 102 add(j+n,j); 103 } 104 else 105 { 106 add(i,j+n); 107 add(j,i+n); 108 } 109 } 110 else if(i % 2 == 1 && j % 2 == 1 ) 111 { 112 if(val == 0) 113 { 114 add(i+n,j); 115 add(j+n,i); 116 } 117 else 118 { 119 add(i,i+n); 120 add(j,j+n); 121 } 122 } 123 else 124 { 125 if(val == 0 ) 126 { 127 add(i,j); 128 add(j,i); 129 add(i+n,j+n); 130 add(j+n,i+n); 131 } 132 else 133 { 134 add(i+n,j); 135 add(j,i+n); 136 add(j+n,i); 137 add(i,j+n); 138 } 139 } 140 } 141 } 142 } 143 // tarjan 144 dep = 0 ; 145 memset(dfn,-1,sizeof(dfn)); 146 memset(instack,0,sizeof(instack)); 147 top = 0 ; 148 scnt = 0 ; 149 for(int i = 1 ; i <= n * 2 ; i++ ) 150 { 151 if(dfn[i] == -1) 152 tarjan(i); 153 } 154 bool flag; 155 flag = true; 156 for(int i = 1 ;i <= n ; i ++ ) 157 { 158 if(col[i] == col[i+n]) 159 { 160 flag = false; 161 break; 162 } 163 } 164 return flag; 165 } 166 int main() 167 { 168 while(scanf("%d",&n)!=EOF) 169 { 170 for(int i = 1; i <= n ; i ++ ) 171 { 172 for(int j = 1; j <= n ; j ++ ) 173 { 174 scanf("%d",&b[i][j]); 175 } 176 } 177 bool flag; 178 flag = true; 179 for(int i = 0 ;i < 32 ;i ++ ) 180 { 181 flag = flag & work(i); 182 if(!flag ) break; 183 } 184 if(flag) 185 printf("YES\n"); 186 else printf("NO\n"); 187 } 188 return 0; 189 }