分析
首先看题目发现这是一个连通性问题,就是在某个半径下一些塔的控制范围有重叠部分,两塔有重叠就说明它们连成了一片,同理若某塔控制了海滩边缘,这一侧边缘也与它相连,海滩受保护当且仅当左右摊联通,显然这是一个满足二分的东西,半径越大可连的边单调不降,但我们并不需要二分,只需要一次找出所有边,然后按边权从小到大跑,每次将起终点相连,当左右海滩相连时,当前处理的那一条边的边权即为答案。
code
#include<bits/stdc++.h>
using namespace std;
inline void read(int &res){
char c;
int f=1;
res=0;
c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')res=(res<<1)+(res<<3)+c-48,c=getchar();
res*=f;
}
int n,m;
double x[805],y[805];
int tot;
struct edge{
int fr,to;
double w;
}e[700005];
inline int add(int qq,int mm,double bq){
e[++tot].to=mm;
e[tot].fr=qq;
e[tot].w=bq;
}
inline bool cmp(edge aa,edge bb){
return aa.w<bb.w;
}
int fa[810];
inline int find(int x){
return x==fa[x]?x:fa[x]=find(fa[x]);
}
double ans;
double dis(int xx,int yy){
return sqrt((x[xx]-x[yy])*(x[xx]-x[yy])+(y[xx]-y[yy])*(y[xx]-y[yy]))/2.0;
}
int main()
{
read(n);read(m);
for(int i=1;i<=m;i++){
cin>>x[i]>>y[i];
add(i,m+1,x[i]);
add(i,m+2,n-x[i]);
}
for(int i=1;i<=m+2;i++)fa[i]=i;
for(int i=1;i<=m;i++){
for(int j=i+1;j<=m;j++){
add(i,j,dis(i,j));
}
}
sort(e+1,e+tot+1,cmp);
for(int i=1;i<=tot;i++){
ans=e[i].w;
int kx=find(e[i].fr),ky=find(e[i].to);
if(kx==ky)continue;
fa[kx]=ky;
if(find(m+1)==find(m+2))break;
}
printf("%.2lf",ans);
return 0;
}