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.
void calculate(int a[N], int b[N][N]) { for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { if (i == j) b[i][j] = 0; else if (i % 2 == 1 && j % 2 == 1) b[i][j] = a[i] | a[j]; else if (i % 2 == 0 && j % 2 == 0) b[i][j] = a[i] & a[j]; else b[i][j] = a[i] ^ a[j]; } } }
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
题意:给出一个calculate函数,再给出b数组,问a数组是否存在。
分析:2-SAT问题。一开始,想到把每个a[i]转化成31位二进制,也就是相当于把每个a[i]拆成31个点,然后去建图。
然而这样子却一直MLE。思路也就止于此。然后看了下别人的题解,发现思路是差不多的。但是他是跑31次2-SAT
来判断,也就是对每个a[i]的每一位拿出来,判断31次如果都满足即可输出YES,否则输出NO。
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3656
代码清单:
#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
#include <ctime>
#include <cctype>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
const int maxN = 500 + 5;
const int maxn = 2000 + 5;
int N, n;
int tmap[maxN][maxN];
int dfn[maxn]; //深度优先访问次序
int low[maxn]; //能追溯到的最早次序
int belong[maxn]; //点的属于哪个强连通分量
vector <int> graph[maxn]; //邻接表存图
stack <int> sta; //存储已遍历的节点
bool InStack[maxn]; //是否在栈中
int _index; //索引号
int sccno; //强连通分量个数
void init(){ //初始化
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(belong, 0, sizeof(belong));
memset(InStack, false, sizeof(InStack));
for(int i = 0; i < 2 * n; i++){
graph[i].clear();
}
while(!sta.empty()) sta.pop();
_index = 0;
sccno = 0;
}
void input(){ //输入
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
scanf("%d", &tmap[i][j]);
}
}
}
void createGraph(int k){
for(int i = 0; i < N; i++){
for(int j = 0; j < i; j++){
if(i % 2 == 1 && j % 2 == 1){ // a[i] | a[j]
if((1 << k) & tmap[i][j]){
graph[i + n].push_back(j);
graph[j + n].push_back(i);
}
else{
graph[i + n].push_back(j + n);
graph[j + n].push_back(i + n);
}
}
else if(i % 2 == 0 && j % 2 == 0){ // a[i] & a[j]
if((1 << k) & tmap[i][j]){
graph[i + n].push_back(i);
graph[j + n].push_back(j);
//graph[i].push_back(j);
//graph[j].push_back(i);
}
else{
graph[i].push_back(j + n);
graph[j].push_back(i + n);
}
}
else{ // a[i] ^ a[j]
if((1 << k) & tmap[i][j]){
graph[i].push_back(j + n);
graph[i + n].push_back(j);
graph[j].push_back(i + n);
graph[j + n].push_back(i);
}
else{
graph[i].push_back(j);
graph[j].push_back(i);
graph[i + n].push_back(j + n);
graph[j + n].push_back(i + n);
}
}
}
}
}
void tarjan(int u){ //强连通分量
dfn[u] = low[u] = ++_index;
sta.push(u);
InStack[u] = true;
for(int i = 0; i < graph[u].size(); i++){
int v = graph[u][i];
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u], low[v]);
}
if(InStack[v]){
low[u] = min(low[u], dfn[v]);
}
}
if(dfn[u] == low[u]){
sccno++;
while(!sta.empty()){
int j = sta.top();
sta.pop();
InStack[j] = false;
belong[j] = sccno;
if(j == u) break;
}
}
}
void findscc(){
for(int u = 0; u < 2 * n; u++){
if(!dfn[u]) tarjan(u);
}
}
bool exitSolution(){ //是否有解
for(int u = 0; u < n; u++){
if(belong[u] == belong[u + n])
return false;
}
return true;
}
void solve(){
for(int i = 0; i < N; i++){
for(int j = 0; j <= i; j++){
if(i == j && tmap[i][j] != 0){ //容易WA在这
puts("NO");
return ;
}
if(tmap[i][j] != tmap[j][i]){
puts("NO");
return ;
}
}
}
n = N;
for(int k = 0; k < 31; k++){
init();
createGraph(k);
findscc();
if(!exitSolution()){
puts("NO");
return ;
}
}
puts("YES");
return ;
}
int main(){
while(scanf("%d", &N) != EOF){
input();
solve();
}return 0;
}