题意:有如下的函数
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];
}
}
}
现在,给出矩阵b,问是否有存在的数组a
思路:2-SAT问题。因为是和二进制的操作有关系,我们枚举二进制位,对每一位进行2-SAT判断即可。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=505;
int n;
int b[maxn][maxn];
bool pre()
{
int i,j;
for(i=0;i<n;i++)
if(b[i][i]!=0) return false;
for(i=0;i<n;i++)
for(j=0;j<i;j++)
if(b[i][j]!=b[j][i]) return false;
return true;
}
struct Tsat
{
int n;
vector <int> G[maxn*20];
bool mark[maxn*20];
int S[maxn*100],c;
bool dfs(int x)
{
if(mark[x^1]) return false;
if(mark[x]) return true;
mark[x]=true;
S[c++]=x;
for(int i=0;i<G[x].size();i++)
if(!dfs(G[x][i])) return false;
return true;
}
void init(int n)
{
this->n=n;
for(int i=0;i<n*2;i++) G[i].clear();
memset(mark,0,sizeof(mark));
}
bool solve()
{
for(int i=0;i<n*2;i+=2)
if(!mark[i]&&!mark[i+1]){
c=0;
if(!dfs(i)){
while(c>0) mark[S[--c]]=false;
if(!dfs(i+1)) return false;
}
}
return true;
}
void deal(int i,int j,int k)
{
if(i%2==0 &&j%2==0)
{
if(b[i][j]&(1<<k))
{
G[2*i+1].push_back(2*j+1);
G[2*j+1].push_back(2*i+1);
}
else
{
G[2*i+1].push_back(2*j);
G[2*j+1].push_back(2*i);
}
}
else if(i%2==1 &&j%2==1)
{
if(b[i][j]&(1<<k))
{
G[2*i].push_back(2*j+1);
G[2*j].push_back(2*i+1);
}
else
{
G[2*i].push_back(2*j);
G[2*j].push_back(2*i);
}
}
else
{
if(b[i][j]&(1<<k))
{
G[2*i+1].push_back(2*j);
G[2*j+1].push_back(2*i);
G[2*i].push_back(2*j+1);
G[2*j].push_back(2*i+1);
}
else
{
G[2*i+1].push_back(2*j+1);
G[2*j+1].push_back(2*i+1);
G[2*i].push_back(2*j);
G[2*j].push_back(2*i);
}
}
}
}TSAT;
bool work()
{
int i,j,k;
for(k=0;k<32;k++)
{
TSAT.init(n);
for(i=0;i<n;i++)
for(j=0;j<i;j++)
TSAT.deal(i,j,k);
if(!TSAT.solve()) return false;
}
return true;
}
int main()
{
//freopen("in","r",stdin);
while(scanf("%d",&n)!=EOF)
{
int i,j,k;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&b[i][j]);
if(!pre())
{
printf("NO\n");continue;
}
if(work()) printf("YES\n");
else printf("NO\n");
}
return 0;
}