很裸的2-sat。二分枚举半径,然后对于每个点i枚举j,其中j不是i'.如果dist(i,j)小于半径,那么就连边i->j', j->i',然后判断是否出现冲突。由于用double的话会出现精度误差,而给定点的坐标都是整数.所以,我们可以将其转化为整型处理,不进行开方操作,而比较的时候也是枚举两点间的距离。最后输出答案的时候在开方就行了。
/*
author : csuchenan
prog : hdu 3622
algorithm : 2-sat
*/
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
using std::vector;
const int maxn= 100;
double eps = 1e-5;
vector<int> G[maxn*2+10];
struct Point{
int x , y;
}point[maxn*2+10];
int d[maxn<<1][maxn<<1];
int dfn[maxn*2+10];
int low[maxn*2+10];
int col[maxn*2+10];
int stack[maxn*2+10];
bool ins[maxn*2+10];
int depth, top, color;
int n;
int dist(Point &a, Point &b){
return (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y);
}
int min(int x, int y){
if(x < y)
return x;
return y;
}
void predour(){
memset(d, 0, sizeof(d));
for(int i = 0; i < 2*n; i ++){
for(int j = 0; j < 2*n ; j ++){
d[i][j] = dist(point[i], point[j]);
}
}
}
void init(){
memset(dfn, 0, sizeof(dfn));
memset(ins, 0, sizeof(ins));
memset(col, 0, sizeof(col));
top = color = depth = 0;
for(int i = 0; i < n*2; i ++){
G[i].clear();
}
}
void add_edge(int i, int j){
G[i].push_back(j);
}
void tarjan(int v){
dfn[v] = low[v] = ++ depth;
ins[v] = true;
stack[top ++] = v ;
for(int i = 0; i != G[v].size(); i ++){
int u = G[v][i];
if(dfn[u]==0){
tarjan(u);
low[v] = min(low[v], low[u]);
}
else if(ins[u]){
low[v] = min(low[v], dfn[u]);
}
}
if(low[v]==dfn[v]){
int k;
color++;
do{
k = stack[--top];
ins[k] = false;
col[k] = color;
}while(k!=v);
}
}
bool two_sat(){
//tarjan
for(int i = 0; i < 2*n; i ++){
if(dfn[i]==0){
tarjan(i);
}
}
//check
for(int i = 0; i < n; i ++){
if(col[i<<1] == col[i<<1|1]){
return false;
}
}
return true;
}
bool test(int R){
init();//建图前先初始化
//建图
for(int i = 0; i < n; i ++){
for(int j = i+1; j < n; j ++){
if(d[i<<1][j<<1] < R){
add_edge(i<<1, j<<1|1);
add_edge(j<<1, i<<1|1);
}
if(d[i<<1|1][j<<1] < R){
add_edge(i<<1|1, j<<1|1);
add_edge(j<<1, i<<1);
}
if(d[i<<1|1][j<<1|1] < R){
add_edge(i<<1|1, j<<1);
add_edge(j<<1|1, i<<1);
}
if(d[i<<1][j<<1|1] < R){
add_edge(i<<1, j<<1);
add_edge(j<<1|1, i<<1|1);
}
}
}
//进行判断
return two_sat();
}
int main(){
// freopen("test.in", "r", stdin);
while(scanf("%d", &n)!=EOF){
for(int i = 0; i < n; i ++){
scanf("%d%d%d%d", &point[i<<1].x, &point[i<<1].y, &point[i<<1|1].x, &point[i<<1|1].y);
}
predour();
int l = 0 , r = 800000001;
while(l < r){
int m = (l + r)>>1;
if(test(m))
l = m+1;
else
r = m;
}
printf("%.2f\n", sqrt(l-1.0)*0.5);
}
return 0;
}