题解—Star Way To Heaven
考场上打了一个看起来就很假的思路。
二维平面,为什么考场上没想到做圆这个操作呢?
很\(nb\)的一个思路。
因为让求最小值最大,所以还是二分答案比较好想到。
写一写如何\(check\)(土哥考场就切,tql)
当给定一个\(ans\)的时候,我们可以以每个点为圆心搞一个圆,而边界直接搞两条线。
如果他们有重合部分,就连边。
最后看一下上下边界连不连通,如果连通,说明这个半径下不可行。
由于带个\(log\)所以有点\(TLE\)
所以他直接求最小生成树。
一共有\(k^2\)条边,如果我们可以让上下边界通过若干条边相连,并且保证我们选的边都是最短的,那就说明我们必须从这些边里面选择一条走过去,否则无法跨过这条线。
所以最小生成树建到把上下边界相连就行了,没必要全建出来。
还帮我学习了一下\(prim\)算法,\(n^2\)的,完全图比\(kul\)少一个\(log\)
也是可以保证每次选的边都是最小的。
这道题给了求最小值最大一个新思路,用最小生成树,然后找里面最大的边。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define R register int
#define int long
#define printf Ruusupuu = printf
#define scanf Ruusupuu = scanf
#define freopen rsp_5u = freopen
int Ruusupuu ;
FILE * rsp_5u ;
using namespace std ;
typedef long long L ;
typedef long double D ;
typedef pair<int , int> PI ;
const int N = 6e3 + 10 ;
inline void of(){ freopen( "in.in" , "r" , stdin ) , freopen( "out.out" , "w" , stdout ) ; }
inline void cf(){ fclose( stdin ) , fclose( stdout ) ; }
inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - '0' ) , ch = getchar() ;
return fg ? -w : w ;
}
int n , m , k , x [N] , y [N] ;
D ans , d [N] ;
bool vis [N] ;
inline D dis( int xx , int yy ){
if( xx == k + 1 ) return (D)y [yy] ;
if( xx == k + 2 ) return (D)m - y [yy] ;
if( yy == k + 1 ) return (D)y [xx] ;
if( yy == k + 2 ) return (D)m - y [xx] ;
return (D)sqrt( (D)( x [xx] - x [yy] ) * ( x [xx] - x [yy] ) + (D)( y [xx] - y [yy] ) * ( y [xx] - y [yy] ) ) ;
}
void sc(){
n = read() , m = read() , k = read() ;
for( R i = 1 ; i <= k ; i ++ ) x [i] = read() , y [i] = read() ;
}
void prim(){
for( R i = 1 ; i < k + 2 ; i ++ ) d [i] = 1e12 ;
for( R i = 1 ; i < k + 2 ; i ++ ){
int x = 0 ;
for( R j = 1 ; j <= k + 2 ; j ++ )
if( ( !vis [j] ) && ( x == 0 || d [j] < d [x] ) ) x = j ;
vis [x] = 1 ;
ans = max( ans , d [x] ) ;
if( vis [k + 1] ) break ;
for( R j = 1 ; j <= k + 2 ; j ++ )
if( !vis [j] ) d [j] = min( d [j] , dis( x , j ) ) ;
}
printf( "%Lf\n" , ans / 2.0 ) ;
}
void work(){
prim() ;
}
signed main(){
// of() ;
sc() ;
work() ;
// cf() ;
return 0 ;
}
$The \ light \ has \ betrayed \ me$

浙公网安备 33010602011771号