第一道2-SAT,做的挺纠结的主要是添加边的时候不细心,导致各种错误,检查了n遍终于A了。
2-SAT问题就是一组布尔变量x,分别代表两种对立的选择。还有一组变量之间的或关系的约束条件。看能否给这些变量赋值,使最后赋值的结果能够满足约束条件。
用2-SAT解决关键问题,就是确定变量及其取值所代表的的含义,还有约束条件或关系的确立。我总结了一种方法来确定或关系,就是先写出不满足题目约束条件的与关系,然后再取或关系得到需满足的或关系。比如xi和xj不能同时取1,也就是最后xi和xj的赋值不能够使(xi与xj)==1,也就是必须是(xi与xj)‘=(xi'或xj')==1,从而确定了xi'或xj'==1这一关系,就是xi取0或xj取0这一约束关系。
对于本题,每个点用一个变量来表示,取1表示向上确定正方形,0表示向下确定正方形。二分答案。对于当前的mid值,确定约束条件。如果两个点之间x坐标之差的绝对值大于等于mid的话,就不要考虑关于这两个点的约束条件,因为不管这么取,他俩互不影响,肯定不会相交,对于小于mid的,根据y坐标情况确定约束条件,总共有3种情况,具体代码。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#define LL long long
#define myabs(x) ((x)>0?(x):(-(x)))
using namespace std;
const int inf=0x3f3f3f3f;
const int maxm=100+10;
const int maxn=100*2+10;
struct Edge
{
int v,next;
};
struct node
{
int x,y;
};
node p[maxm];
Edge e[maxn*maxn];
int mark[maxn];
int head[maxn],S[maxn];
int n,tot,top;
bool cmp(node a,node b)
{
if(a.y==b.y) return a.x<b.x;
else return a.y<b.y;
}
void addedge(int u,int v)
{
e[tot].v=v; e[tot].next=head[u];
head[u]=tot++;
}
int dfs(int u)
{
if(mark[u]) return 1;
if(mark[u^1]) return 0;
mark[u]=1;
int v,i;
S[top++]=u;
for(i=head[u];i!=-1;i=e[i].next)
{
v=e[i].v;
if(!dfs(v)) return 0;
}
return 1;
}
int solve()
{
int low=0,high=40000,mid;
int i,j;
while(low<=high)
{
mid=(low+high)/2;
tot=0;
memset(head,-1,sizeof(head));
memset(mark,0,sizeof(mark)); //新的2-SAT,注意初始化
int flag=1;
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(myabs(p[i].x-p[j].x)<mid)
{
if((p[j].y-p[i].y)<2*mid&&(p[j].y-p[i].y)>=mid)
{
addedge(j*2,i*2);
addedge(i*2+1,j*2+1);
}
else if((p[j].y-p[i].y)<mid&&(p[j].y-p[i].y)>0)
{
addedge(j*2,i*2);
addedge(i*2+1,j*2+1);
addedge(j*2,i*2+1);
addedge(i*2,j*2+1);
addedge(j*2+1,i*2);
addedge(i*2+1,j*2);
}
else if((p[j].y-p[i].y)==0)
{
addedge(j*2+1,i*2);
addedge(i*2+1,j*2);
addedge(j*2,i*2+1);
addedge(i*2,j*2+1);
}
}
}
}
for(i=0;i<n;i++)
{
if(!mark[i*2]&&!mark[i*2+1])
{
top=0;
if(!dfs(i*2))
{
while(top>0) mark[S[--top]]=0;
if(!dfs(i*2+1))
{
flag=0;
break;
}
}
}
}
if(flag) low=mid+1;
else high=mid-1;
}
return low-1;
}
int main()
{
int T;
cin>>T;
while(T--)
{
scanf("%d",&n);
int i;
for(i=0;i<n;i++)
scanf("%d%d",&p[i].x,&p[i].y);
sort(p,p+n,cmp);
int ans=solve();
printf("%d\n",ans);
}
return 0;
}