poj2296

题解:

二分一下答案

对于每一个区间,都可以放在上面和下面

判断是否交叉

代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1005;
int flag[N],n,x[N],y[N],b[N][N],ne[2*N*N],fi[N],zz[4*N*N],num;
int t,zhan[N],T,dfn[N],m,l,q,ans,low[N],an[N];
void jb(int x,int y)
{
    ne[++num]=fi[x];
    fi[x]=num;
    zz[num]=y;
}
void dfs(int x)
{
    low[x]=dfn[x]=++l;
    zhan[++t]=x;
    flag[x]=true;
    for (int i=fi[x];i!=0;i=ne[i])
     {
         if (an[zz[i]])continue;
        if(!dfn[zz[i]])dfs(zz[i]);
        if(!flag[zz[i]])low[x]=min(low[x],dfn[zz[i]]);else
        low[x]=min(low[x],low[zz[i]]);
     }
    if (dfn[x]==low[x])
     {
         ans++;
         while (zhan[t]!=x)
          {
              flag[zhan[t]]=false;
              an[zhan[t--]]=ans;
          }
         an[zhan[t--]]=ans;
         flag[x]=false;
     }
}
void init()
{
    ans=num=l=0;
    memset(fi,0,sizeof fi);
    memset(an,0,sizeof an);
    memset(dfn,0,sizeof dfn);
}
void build(int r)
{  
    init();  
    for (int i=0;i<n;i++)
     for (int j=i+1;j<n;j++)
      {  
        if (abs(x[i]-x[j])>=r)continue;  
        if (abs(y[i]-y[j])>=2*r)continue;  
        if (abs(y[i]-y[j])<r)
         {  
            if (y[i]>y[j])
             { 
                jb(i,j+n);  
                jb(i+n,i);  
                jb(j,j+n);  
                jb(j+n,i);  
             }
            else if (y[i]<y[j])
             {  
                jb(j,i+n);  
                jb(j+n,j);  
                jb(i,i+n);  
                jb(i+n,j);  
             }
            else
             {  
                jb(i,j+n);  
                jb(i+n,j);  
                jb(j,i+n);  
                jb(j+n,i);  
             }       
         }
        else
         {  
            if (y[i]>y[j])
             {  
                jb(i+n,j+n);  
                jb(j,i);  
             }
            else
             {  
                jb(j+n,i+n);  
                jb(i,j);  
             }  
         }  
      }   
}
int main()
{
    scanf("%d",&T);
    while (T--)
     {
        scanf("%d",&n);
        for (int i=0;i<n;i++)scanf("%d%d",&x[i],&y[i]);
        int l=0,r=20005;
        while (l<r)
         {
             int mid=(l+r+1)/2;
             build(mid);
             for (int i=0;i<2*n;i++)
              if (!dfn[i])dfs(i);
             for (int i=0;i<n;i++)
             if (an[i]==an[i+n])r=mid-1;
            if (r>=mid)l=mid;  
         }
        printf("%d
",l); 
     }
}
原文地址:https://www.cnblogs.com/xuanyiming/p/8136903.html