说在前面
久违的1A,开心qvq
题目
题目大意
给定N个点对,在每一个点对中选择一个点画圆,半径自定,要求画的圆不能有并(不存在一个位置同时被多个圆覆盖)
得分是所有圆中半径最小的那个,需要求出最大得分。
输入输出格式
输入格式:
包含多组数据,对于每一组数据:
第一行一个整数N,表示点对数(不超过100)
接下来每行四个整数 x1 , y1 , x2 , y2 描述一个点对
输出格式:
对于每组数据,输出一行一个实数表示答案(保留两位小数)
解法
简单2-sat题
要求每一个点对「选且仅选一个点」,并且选的点之间有限制,这就是一个2-sat模型
二分答案(半径),然后用这个距离去判断冲突,建图跑2-sat
有可行解说明当前可以作为答案,不然就不行
下面是优美的代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
int N , C_cnt , oppo[205] , head[205] , tp ;
struct Path{
int pre , to ;
}p[2*(1+200)*200/2 + 5 ] ;
struct Points{
int x , y ;
double dist2( const Points &A ){
return ( A.x - x ) * ( A.x - x ) + ( A.y - y ) * ( A.y - y ) ;
}
}C[205] ;
void In( int t1 , int t2 ){
p[++tp].pre = head[t1] ;
p[ head[t1] = tp ].to = t2 ;
}
double mid ;
void build(){
double tmp = 4 * mid * mid ; // mid is radius , half of the distence
for( int i = 1 ; i <= C_cnt ; i ++ )
for( int j = i + 1 ; j <= C_cnt ; j ++ )
if( C[i].dist2( C[j] ) <= tmp ){
In( i , oppo[j] ) ;
In( j , oppo[i] ) ;
}
}
int sta[205] , topp ;
int dfn[205] , dfs_c , scc[205] , scc_cnt ;
int dfs( int u ){
sta[++topp] = u ;
int lowu = dfn[u] = ++dfs_c ;
for( int i = head[u] ; i ; i = p[i].pre ){
int v = p[i].to ;
if( !dfn[v] ) lowu = min( lowu , dfs( v ) ) ;
else if( !scc[v] ) lowu = min( lowu , dfn[v] ) ;
}
if( lowu == dfn[u] ){
scc_cnt ++ ;
while( 1 ){
int x = sta[topp--] ;
scc[x] = scc_cnt ;
if( x == u ) break ;
}
} return lowu ;
}
void clear_G(){
dfs_c = tp = 0 ;
memset( head , 0 , sizeof( head ) ) ;
memset( scc , 0 , sizeof( scc ) ) ;
memset( dfn , 0 , sizeof( dfn ) ) ;
}
bool check(){
clear_G() ; build() ;
for( int i = 1 ; i <= C_cnt ; i ++ )
if( !dfn[i] ) dfs( i ) ;
for( int i = 1 ; i <= C_cnt ; i ++ ){
if( scc[i] == scc[ oppo[i] ] ) return false ;
} return true ;
}
void solve(){
double lf = 0 , rg = 20000 * 2 , ans ;
while( lf <= rg - 0.0005 ){
mid = ( lf + rg ) / 2 ;
if( check() ){
ans = mid ;
lf = mid ;
} else rg = mid ;
}
printf( "%.2f\n" , ans ) ;
}
int main(){
while( scanf( "%d" , &N ) != EOF ){
C_cnt = 0 ;
for( int i = 1 , a1 , b1 , a2 , b2 ; i <= N ; i ++ ){
scanf( "%d%d%d%d" , &a1 , &b1 , &a2 , &b2 ) ;
C[++C_cnt] = ( Points ){ a1 , b1 } ;
C[++C_cnt] = ( Points ){ a2 , b2 } ;
oppo[C_cnt] = C_cnt - 1 ;
oppo[C_cnt - 1] = C_cnt ;
}
solve() ;
}
}