poj 2296

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



發佈了187 篇原創文章 · 獲贊 3 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章