Description
Assume that each city is a point on the plane, and its label is a text bounded in a square with edges parallel to x and y axis. The label of each city should be located such that the city point appears exactly in the middle of the top or bottom edges of the label. In a good labeling, the square labels are all of the same size, and no two labels overlap, although they may share one edge. Figure 1 depicts an example of a good labeling (the texts of the labels are not shown.)
Given the coordinates of all city points on the map as integer values, you are to find the maximum label size (an integer value) such that a good labeling exists for the map.
![](https://i-blog.csdnimg.cn/blog_migrate/d4cd142537627cd6b2b2d753288d1ca6.jpeg)
Input
Output
Sample Input
1 6 1 1 2 3 3 2 4 4 10 4 2 5
Sample Output
2
Source
题意:给出以下二维坐标点,然后让你往平面上放正方形,点必须落在正方形上面边的中点或者下面边的中点,正方形不能重叠,可以共用边。问最大正方形边的边长。
分析:这种最大化最小值或者最小化最大值的问题,我们都可以种二分+判断的方法来解,这个也不例外,关键是判断部分
我们现在二分枚举边长为diff,然后所有的点就变成了在正方形上面或者下面的问题了,二选一的问题很明显可以用2-set来判断的
这个题目的关键在于理解他们之间的二元关系并建图,下面我们来分析
首先,对于一个点a,在正方形的上边上,设为点a,在下边上设为点-a。
b同样的,上边上设为点b,下边上设为-b
对于任意两个点a和b
如果a和b的横坐标只差小于diff
如果纵坐标值相等,那么只能是一个在上面一个在下面,表示而二元关系为(a | b)即a和b只能有一个在上边上,改写成等价形式
(a&-b)|(-a&b)即a在上边则b必然在下边,a在下边的话b必然在上边,我们在加边的时候要求强连通分量,所以这里可以按无向边建图。
如果纵坐标的值小于diff,则纵坐标值大的所在正方形必然位于上面,小的位于下面,我们假设a的纵坐标大于b,我们可以让a–>-a,-b–>b,为什么呢?因为我们必然要让a的四边形位于上面,即点在下边上,这样连边如果点在上边,则会形成a个-a属于同一个强连通分量导致可行,so..
如果纵坐标的值小于2*diff,同样假设a纵坐标的大于b,那么a的四边形在下,则b的必然在下,b的在上则a的必然也在上所以-a–>-b,b–>a
这用只要同s-set跑是否可行就ok
对其中的一些关系的建图还是很经典的。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
using namespace std;
stack<int>s;
const int N=105;
struct node{
int x,y;
}point[N];
struct node1{
int now,next;
}str[N*N*4];
int head[2*N],tot;
int dfs[2*N],ins[2*N],belong[2*N],low[2*N],ans,tol;
void add(int x,int y)
{
str[tot].now=y;
str[tot].next=head[x];
head[x]=tot++;
}
void tarjan(int u)
{
ins[u]=1;
dfs[u]=low[u]=tol++;
s.push(u);
for(int i=head[u];i!=-1;i=str[i].next)
{
int v=str[i].now;
if(dfs[v]==-1)
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(ins[v])
low[u]=min(low[u],dfs[v]);
}
if(dfs[u]==low[u])
{
while(1)
{
int q=s.top();
s.pop();
ins[q]=0;
belong[q]=ans;
if(q==u) break;
}
ans++;
}
}
bool ok(int n)
{
memset(dfs,-1,sizeof(dfs));
memset(ins,0,sizeof(ins));
ans=tol=0;
for(int i=0;i<2*n;i++)
if(dfs[i]==-1)
tarjan(i);
for(int i=0;i<2*n;i+=2)
if(belong[i]==belong[i+1])
return false;
return true;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d%d",&point[i].x,&point[i].y);
int l=0,r=80000;
while(r>=l)
{
int temp=(l+r)/2;
memset(head,-1,sizeof(head));
tot=0;
for(int i=0;i<n-1;i++)
{
for(int j=i+1;j<n;j++)
{
if(abs(point[i].x-point[j].x)>=temp) continue;
if(abs(point[i].y-point[j].y)<temp)
{
if(point[i].y==point[j].y)
{
add(2*i,2*j+1);
add(2*i+1,2*j);
add(2*j+1,2*i);
add(2*j,2*i+1);
}
else if(point[i].y>point[j].y)
{
add(2*i+1,2*i);
add(2*j,2*j+1);
}
else
{
add(2*j+1,2*j);
add(2*i,2*i+1);
}
}
else if(abs(point[i].y-point[j].y)<2*temp)
{
if(point[i].y>point[j].y)
{
add(2*i+1,2*j+1);
add(2*j,2*i);
}
else
{
add(2*j+1,2*i+1);
add(2*i,2*j);
}
}
}
}
if(ok(n)) l=temp+1;
else r=temp-1;
}
printf("%d\n",r);
}
}