题目:http://poj.org/problem?id=2296
题意:给你n个点,要你在这n个点上方一个正方形,点只能在正方形的上边或下边的中点上,所有正方形大小一样,不能重叠,求最大的正方形。。。
分析:跟HDU 3622 Bomb Game差不多,只是变成正方形判定而已,分清楚各种状态就行
PS:强连通老是写错那么几个变量,调试好久啊= =,不过还是1Y了
代码:
#include<cstdio>
#include<iostream>
using namespace std;
const int mm=88888;
const int mn=222;
int ver[mm],next[mm];
int x[mn],y[mn],head[mn],dfn[mn],low[mn],q[mn],id[mn];
int i,j,k,l,r,m,n,idx,top,cnt,edge,t,ans;
void add(int u,int v)
{
ver[edge]=v,next[edge]=head[u],head[u]=edge++;
}
void dfs(int u)
{
dfn[u]=low[u]=++idx;
q[top++]=u;
for(int i=head[u],v;i>=0;i=next[i])
if(!dfn[v=ver[i]])
dfs(v),low[u]=min(low[u],low[v]);
else if(!id[v])low[u]=min(low[u],dfn[v]);
if(low[u]==dfn[u])
{
id[u]=++cnt;
while(q[--top]!=u)id[q[top]]=cnt;
}
}
void Tarjan()
{
for(idx=top=cnt=i=0;i<n+n;++i)dfn[i]=id[i]=0;
for(i=0;i<n+n;++i)
if(!dfn[i])dfs(i);
}
int abc(int x)
{
return x<0?-x:x;
}
bool ok()
{
for(edge=i=0;i<n+n;++i)head[i]=-1;
for(i=0;i<n;++i)
for(j=i+1;j<n;++j)
if(abc(x[i]-x[j])<m&&abc(y[i]-y[j])<2*m)
{
if(abc(y[i]-y[j])>=m)
{
if(y[i]<y[j])
{
add(i<<1|1,j<<1|1);
add(j<<1,i<<1);
}
else
{
add(i<<1,j<<1);
add(j<<1|1,i<<1|1);
}
}
else if(y[i]<y[j])add(i<<1|1,i<<1),add(j<<1,j<<1|1);
else if(y[i]>y[j])add(i<<1,i<<1|1),add(j<<1|1,j<<1);
else
{
add(i<<1|1,j<<1),add(i<<1,j<<1|1);
add(j<<1,i<<1|1),add(j<<1|1,i<<1);
}
}
Tarjan();
for(i=0;i<n+n;i+=2)
if(id[i]==id[i^1])return 0;
return 1;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=0;i<n;++i)
scanf("%d%d",&x[i],&y[i]);
ans=l=0,r=1e5;
while(l<=r)
{
m=(l+r)>>1;
if(ok())ans=m,l=m+1;
else r=m-1;
}
printf("%d\n",ans);
}
return 0;
}