做之前就听说这题是2-SAT,做的时候还是出了问题,毕竟之前就只做过一道2-SAT的题,建图的时候我想建一个500*32*2的图,不过我觉得这样的图太大了,跑起来肯定就TLE,不过又没有其他太好的想法,只能再去看题解,发现题解是把这个图做成500*2的,然后跑32遍2-SAT,想明白这点以后就去接着写了,不过跑出来结果还是不对,然后就觉得自己的边建的太多了,2-SAT连边的要求是选这个以后就必须选另一个,如果两个都能选的话就不能连边了,这样建图以后样例还是跑不过去,而且是建图的时候就有问题,后来发现是if句的少加一个大括号,各种伤不起……最近状态不太好,希望赶紧把状态调整好吧。
#include <iostream>
#include <cstdio>
#include <string.h>
#include <vector>
#include <stack>
using namespace std;
#define M 1010 //题目中可能的最大点数
stack<int> s; //tarjan 算法中的栈
bool ins[M]; //检查是否在栈中
int dfn[M]; //深度优先搜索访问次序
int low[M]; //能追溯到的最早的次序
int scnt=0; //有向图强连通分量个数
int cnt=0; //索引号
vector<int> g[M],g2[M]; //邻接表表示
int belong[M]; //记录每个点在第几号强连通分量里
int ant[M]; //缩点后互斥的点
int color[M]; //用于拓扑排序的染色
int ind[M]; //统计入度
int n; //图的规模
int b[505][505];
void tarjan(int i)
{
int j;
dfn[i]=low[i]=cnt++;
ins[i]=true;
s.push(i);
for (int e=0; e<g[i].size(); e++)
{
j=g[i][e];
if (dfn[j]==-1)
{
tarjan(j);
low[i]=min(low[i],low[j]);
}
else if (ins[j])
low[i]=min(low[i],dfn[j]);
}
if (dfn[i]==low[i])
{
scnt++;
do
{
j=s.top();
s.pop();
ins[j]=false;
belong[j]=scnt;
}
while (j!=i);
}
}
bool solve() //N是此图中点的个数,注意是0-cnted!
{
memset(ins,0,sizeof(ins));
memset(dfn,-1,sizeof(dfn));
memset(low,-1,sizeof(low));
memset(ind,0,sizeof(ind));
memset(color,0,sizeof(color));
scnt=cnt=0;
for(int i=0; i<2*n; i++)
if(dfn[i]==-1)
tarjan(i);
//cout<<scnt<<endl;
for(int i=0; i<n; i++)
if(belong[i]==belong[i+n])
{
return false;
}
return true;
}
int main()
{
//freopen("input.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
scanf("%d",&b[i][j]);
}
bool ok=true;
for(int k=0; k<32; k++)
{
for(int i=0; i<2*n; i++)
g[i].clear();
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
if (i == j)
{
if(b[i][j])
{
ok=false;
break;
}
}
else if (i % 2 == 1 && j % 2 == 1)
if(b[i][j]&(1<<k))
{
g[i].push_back(j+n);
g[j].push_back(i+n);
}
else
{
g[i].push_back(j);
g[j].push_back(i);
}
else if (i % 2 == 0 && j % 2 == 0)
if(b[i][j]&(1<<k))
{
g[i+n].push_back(j+n);
g[j+n].push_back(i+n);
}
else
{
g[i+n].push_back(j);
g[j+n].push_back(i);
}
else
{
if(b[i][j]&(1<<k))
{
g[i].push_back(j+n);
g[j].push_back(i+n);
g[i+n].push_back(j);
g[j+n].push_back(i);
}
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);
}
}
}
if(!solve())
{
ok=false;
break;
}
}
if(ok)
printf("YES\n");
else printf("NO\n");
}
}