第一道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;
}