ZROI2018提高day4t2

传送门

分析

我们二分球的直径,然后就像奶酪那道题一样,将所有距离相遇直径的点用并查集连在一起,然后枚举所有与上边的顶距离小于直径的点和所有与下边的距离小于直径的点,如果它们被并查集连在一起则代表这个球无法通过。于是可以得到答案。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int n,fa[1100],x[1100],y[1100],is1[1100],is2[1100];
double L;
inline void init(){
      for(int i=1;i<=n;i++)fa[i]=i;
      memset(is1,0,sizeof(is1));
      memset(is2,0,sizeof(is2));
}
inline int sf(int x){return fa[x]==x?x:fa[x]=sf(fa[x]);}
inline double d(int a,int b){
      return double(sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b])));
}
inline bool ck(double mid){
      int i,j,k;
      init();
      for(i=1;i<=n;i++){
          if(L-y[i]<mid)is1[i]=1;
          if(y[i]<mid)is2[i]=1;
      }
      for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
          if(d(i,j)<mid&&sf(i)!=sf(j))fa[sf(i)]=sf(j);
      for(i=1;i<=n;i++)
        if(is1[i])
          for(j=1;j<=n;j++)
            if(is2[j])
              if(sf(i)==sf(j))return 0;
      return 1;
}
int main(){
      int i,j,k;
      double le,ri,mid;
      cin>>n>>L;
      for(i=1;i<=n;i++){
          scanf("%d%d",&x[i],&y[i]);
      }
      le=0,ri=L+1;
      while(ri-le>0.0001){
          mid=(le+ri)/2;
          if(ck(mid))le=mid;
           else ri=mid;
      }
      printf("%0.3lf
",le);
      return 0;
}
原文地址:https://www.cnblogs.com/yzxverygood/p/9688486.html