【2-SAT】 HDU 4421 Bit Magic
最近各种位运算的小知识我也是醉了
对于每一位数 2-SAT
#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); addedge(j, i+n); } else//(i==0->i==1),(j==0->j==1) { addedge(i+n, 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; }