题目大意:
给一个有一个N维向量通过一定的逻辑运算得到的矩阵,问存在不存在一个N维向量满足要求。
解题思路:
一看到给出逻辑运算结果,求存在不存在,马上就能想到时2-SAT。
不过这里的每个元素都是整数,而不是布尔类型,我们就可以把正数看做一个二进制序列,这样每一位都是布尔类型了。由于每一位之间时完全独立的,我们就可以通过一个循环,每次只对一位执行2-SAT,而不必同时把所有位都放到一张图中(如果这样做会MLE)。然后如果每次2-SAT都有解,那么整个矩阵有解。
附上一张从大佬的博客截过来的2-SAT逻辑运算转化表:
AC代码:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <stack> #include <cstdlib> #include <cmath> #include <ctime> #include <map> #include <string> #include <set> using namespace std; #define INF 0x3f3f3f3f #define LL long long #define fi first #define se second #define mem(a,b) memset((a),(b),sizeof(a)) #pragma #pragma comment(linker, "/STACK:1024000000,1024000000") const int MAXN=500+3; const int MAXV=MAXN*2; int N,V; vector<int> G[MAXV],rG[MAXV]; vector<int> vs; int save[MAXN][MAXN]; bool used[MAXV]; int cmp[MAXV]; void init()//初始化 { for(int i=0;i<2*N;++i) { G[i].clear(); rG[i].clear(); } } void dfs(int v)//正向dfs { used[v]=true; for(int i=0;i<G[v].size();++i) if(!used[G[v][i]]) dfs(G[v][i]); vs.push_back(v); } void rdfs(int v,int k)//反向dfs { used[v]=true; cmp[v]=k; for(int i=0;i<rG[v].size();++i) if(!used[rG[v][i]]) rdfs(rG[v][i],k); } int scc()//Kosaraju算法求强连通分量 { mem(used,0); vs.clear(); for(int v=0;v<V;++v) if(!used[v]) dfs(v); mem(used,0); int k=0; for(int i=vs.size()-1;i>=0;--i) if(!used[vs[i]]) rdfs(vs[i],k++); return k; } int main() { while(~scanf("%d",&N)) { bool ans=true; for(int i=0;i<N;++i) for(int j=0;j<N;++j) { scanf("%d",&save[i][j]); if(i==j&&save[i][j]!=0) ans=false; if(i>j&&save[i][j]!=save[j][i]) ans=false; } V=N*2; for(int i=0;i<32;++i)//每一位分开处理 { init(); bool ok=true; for(int i=0;i<N;++i) for(int j=i+1;j<N;++j) { if((i&1)&&(j&1))//or { if(save[i][j]&1) { G[i+N].push_back(j); G[j+N].push_back(i); rG[j].push_back(i+N); rG[i].push_back(j+N); } else { G[i].push_back(i+N); G[j].push_back(j+N); rG[i+N].push_back(i); rG[j+N].push_back(j); } } else if(i%2==0&&j%2==0)//and { if(save[i][j]&1) { G[i+N].push_back(i); G[j+N].push_back(j); rG[i].push_back(i+N); rG[j].push_back(j+N); } else { G[i].push_back(j+N); G[j].push_back(i+N); rG[j+N].push_back(i); rG[i+N].push_back(j); } } else//xor { if(save[i][j]&1) { G[i].push_back(j+N); G[j+N].push_back(i); G[i+N].push_back(j); G[j].push_back(i+N); rG[j+N].push_back(i); rG[i].push_back(j+N); rG[j].push_back(i+N); rG[i+N].push_back(j); } else { G[i].push_back(j); G[j].push_back(i); G[i+N].push_back(j+N); G[j+N].push_back(i+N); rG[j].push_back(i); rG[i].push_back(j); rG[j+N].push_back(i+N); rG[i+N].push_back(j+N); } } } scc(); for(int i=0;i<N;++i) if(cmp[i]==cmp[i+N]) { ok=false; break; } if(!ok) { ans=false; break; } for(int i=0;i<N;++i) for(int j=0;j<N;++j) save[i][j]>>=1; } puts(ans?"YES":"NO"); } return 0; }