10.22T1 二分+并查集
6028 -- 【2020级互测D8T1】⑩⑨⑥的穿行
Description
朝比奈实 玖 瑠 ,使用TPDD进行时间穿行的未来人。
由于这项技术过于暴力 (简单来说就是在时间平面上打洞),加之春日带来的资讯爆炸
使得堆叠的时间平面彻底截断,导致实玖瑠进行穿行需要冒一定的风险。
复杂的时间穿行过程可以抽象为从平面x轴的正无穷远处走向负无穷远。TPDD的功率显然是有限的,所以实玖瑠只能够在平面y= 的直线与X轴所夹的部分里移动。TPDD的移动方式非常的怪异,它会生成一个直径为 的圆来保护使用者,并且从正无穷远处向负无穷远处移动,直径越大,能量越足,移动速度也就最快。但是,时间穿行的风险就在于时间平面上有许多特异点,一旦被卷入其中,就再也不能回到原来的时间点。在从正无穷远走向负无穷远的过程中,圆可以任意的移动,但是不能碰到特异点和越过边界。
实玖瑠已经了解到,在她将要进行移动的部分平面上,有N个特异点,第i个点的坐标是xi,yi 。为了能够在保证安全的情况下尽快完成时间穿行,她需要设定尽量大的直径 。
但是1096只是一个萌物,这样的问题对她来说太困难了,所以请你帮帮她吧!
由于这项技术过于暴力 (简单来说就是在时间平面上打洞),加之春日带来的资讯爆炸
使得堆叠的时间平面彻底截断,导致实玖瑠进行穿行需要冒一定的风险。
复杂的时间穿行过程可以抽象为从平面x轴的正无穷远处走向负无穷远。TPDD的功率显然是有限的,所以实玖瑠只能够在平面y= 的直线与X轴所夹的部分里移动。TPDD的移动方式非常的怪异,它会生成一个直径为 的圆来保护使用者,并且从正无穷远处向负无穷远处移动,直径越大,能量越足,移动速度也就最快。但是,时间穿行的风险就在于时间平面上有许多特异点,一旦被卷入其中,就再也不能回到原来的时间点。在从正无穷远走向负无穷远的过程中,圆可以任意的移动,但是不能碰到特异点和越过边界。
实玖瑠已经了解到,在她将要进行移动的部分平面上,有N个特异点,第i个点的坐标是xi,yi 。为了能够在保证安全的情况下尽快完成时间穿行,她需要设定尽量大的直径 。
但是1096只是一个萌物,这样的问题对她来说太困难了,所以请你帮帮她吧!
Input
输入文件共N+1行。
第一行包括两个整数N,L 。
接下来N行,每行两个整数xi,yi
第一行包括两个整数N,L 。
接下来N行,每行两个整数xi,yi
Output
输出文件仅一行,表示最大的直径。为了防止精度误差,请输出保留三位小数的结果。
Sample Input
1 5
2 2
Sample Output
3.000
【输入输出样例1说明】
显然可以发现,从唯一一个特异点靠L的方向可以通过直径为3的圆
Hint
【数据规模与约定】
对于 30% 的数据,N<=3 。
对于 60% 的数据,N<=80 。
对于 100% 的数据,1<=N<=500,1<=yi<L<10000,-10000<=xi<=10000
对于 30% 的数据,N<=3 。
对于 60% 的数据,N<=80 。
对于 100% 的数据,1<=N<=500,1<=yi<L<10000,-10000<=xi<=10000
二分圆的大小,把两点以及到边缘小于这个距离的合并,如果上下界合并在了一起显然就没有路径
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #define N 100006 6 using namespace std; 7 double eps=1e-6; 8 int fa[N]; 9 struct node { 10 int x,y; 11 } e[N]; 12 int n; 13 double L; 14 int find(int x){ 15 if(x!=fa[x])return fa[x]=find(fa[x]); 16 return fa[x]; 17 } 18 void merge(int x,int y){ 19 int f1=find(x),f2=find(y); 20 if(f1!=f2){ 21 fa[f1]=f2; 22 } 23 } 24 double sq(double x){ 25 return x*x; 26 } 27 double getdis(int i,int j){ 28 return sqrt(sq(e[i].x-e[j].x)+sq(e[i].y-e[j].y)); 29 } 30 bool check(double mid) { 31 for(int i=0;i<=n+1;i++)fa[i]=i; 32 for(int i=1; i<=n; i++){ 33 for(int j=i+1;j<=n;j++){ 34 if(getdis(i,j)<mid)merge(i,j); 35 } 36 if(e[i].y<mid)merge(0,i); 37 if(L-e[i].y<mid)merge(n+1,i); 38 } 39 if(find(0)==find(n+1))return false; 40 return true; 41 } 42 int main() { 43 cin>>n>>L; 44 for(int i=1; i<=n; i++) 45 cin>>e[i].x>>e[i].y; 46 double l=0,r=L,ans; 47 while(r-l>=eps) { 48 double mid=(l+r)/2; 49 // cout<<l<<" "<<r<<" "<<mid<<'\n'; 50 if(check(mid))l=mid,ans=mid; 51 else r=mid; 52 } 53 printf("%.3f",ans); 54 return 0; 55 }
over