最近各种位运算的小知识我也是醉了
对于每一位数 2-SAT
i 为 i这位取0
i+n为 i这位取1
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cmath>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#define cler(arr, val) memset(arr, val, sizeof(arr))
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define IN freopen ("in.txt" , "r" , stdin);
#define OUT freopen ("out.txt" , "w" , stdout);
typedef long long LL;
const int MAXN = 1010;
const int MAXM = 2000010;
const int INF = 0x3f3f3f3f;
const int mod = 1000003;
const double eps= 1e-8;
#define lson l,m, rt<<1
#define rson m+1,r,rt<<1|1
struct Edge
{
int to,next;
} edge[MAXM];
int head[MAXN],tot;
void init()
{
tot = 0;
memset(head,-1,sizeof (head));
}
void addedge (int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值1~scc
int Index,top;
int scc;
bool Instack[MAXN];
int num[MAXN];
void Tarjan(int u)
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u]; i != -1; i = edge[i].next)
{
v = edge[i]. to;
if( !DFN[v] )
{
Tarjan(v);
if(Low[u] > Low[v])Low[u] = Low[v];
}
else if(Instack[v] && Low[u] > DFN[v])
Low[u] = DFN[v];
}
if(Low[u] == DFN[u])
{
scc++;
do
{
v = Stack[--top];
Instack[v] = false;
Belong[v] = scc;
num[scc]++;
}
while(v != u);
}
}
bool solvable(int n)//n是总个数,需要选择一半
{
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
memset(num,0,sizeof(num));
Index = scc = top = 0;
for(int i = 0; i < n; i++)
if(!DFN[i])
Tarjan(i);
for(int i = 0; i < n/2; i++)
{
if(Belong[i] == Belong[i+n/2])
return false;
}
return true;
}
int mp[555][555];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
int n;
while(scanf("%d",&n)!=EOF)
{
bool flag=true;
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
scanf("%d",&mp[i][j]);
for(int i=0; i<n; i++)
for(int j=0; j<=i; j++)
if(i==j&&mp[i][j]!=0) flag=false;
else if(mp[i][j]!=mp[j][i]) flag=false;
if(!flag)
{
puts("NO");
continue;
}
for(int k=0; k<32; k++)
{
init();
for(int i=0; i<n; i++)
{
for(int j=i+1; j<n; j++)
{
if(i==j) continue;
int x=mp[i][j]&(1<<k);
if(i%2==1 && j%2==1)
{
if(x)//(i==1->j==0),(j==1->i==0)
{
addedge(i, j+n);//不取i -> 取 j 矛盾 则 取 j
addedge(j, i+n);
}
else
{
addedge(i+n, i);//取i -> 不取i 矛盾则 不取i
addedge(j+n, j);
}
}
else if(i%2==0 && j%2==0)
{
if(x)//(i==1->j==1),(i==0->i==1),(j==0->j==1)
{
addedge(i, i+n);
addedge(j, j+n);
}
else//(i==0->j==1),(j==0->i==1)
{
addedge(i+n, j);
addedge(j+n, i);
}
}
else
{
if(x)//(i==1->j==0),(j==1->j==0),(i==0->j==1),(j==0->i==1)
{
addedge(i, j+n);
addedge(j, i+n);
addedge(i+n, j);
addedge(j+n, i);
}
else//(i==1->j==1),(j==1->i==1),(i==0->j==0),(j==0->i==0)
{
addedge(i, j);
addedge(j, i);
addedge(i+n, j+n);
addedge(j+n, i+n);
}
}
}
}
if(!solvable(n*2))
{
flag=false;
break;
}
}
if(flag) puts("YES");
else puts("NO");
}
return 0;
}