给n<=100对点,从每对点里面挑一个并以这些挑出的点为圆心画圆,并且这些圆不能互相覆盖,找出一种方案使得这些圆半径中最小的那个最大。
“最小值最大”就是二分答案啦!考虑现在每个点都画出半径x的圆,如何选点呢?
可以发现选了一个点P之后与其距离相差2x内的点Q都不能被选,也就是“与P在同一对的另一个点P' 或 与Q在同一对的另一个点Q'”
有了或语句描述选点冲突,接下来就是2-SAT构图啦!

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 //#include<iostream> 7 using namespace std; 8 9 int n; 10 #define maxn 111*2 11 struct Edge{int to,next;}; 12 #define maxe maxn*maxn 13 struct Graph 14 { 15 Edge edge[maxe];int le; 16 int first[maxn],vis[maxn]; 17 void clear() 18 { 19 le=2; 20 memset(first,0,sizeof(first)); 21 } 22 void insert(int x,int y) 23 { 24 edge[le].to=y; 25 edge[le].next=first[x]; 26 first[x]=le++; 27 } 28 void add_clause(int x,int y) 29 { 30 insert(x^1,y); 31 insert(y^1,x); 32 } 33 int sta[maxn],top; 34 bool dfs(int x) 35 { 36 if (vis[x^1]) return 0; 37 if (vis[x]) return 1; 38 vis[x]=1; 39 sta[++top]=x; 40 for (int i=first[x];i;i=edge[i].next) 41 if (!dfs(edge[i].to)) return 0; 42 return 1; 43 } 44 bool twosat() 45 { 46 memset(vis,0,sizeof(vis)); 47 for (int i=1;i<=n;i++) 48 if (!vis[i*2] && !vis[i*2+1]) 49 { 50 top=0; 51 if (!dfs(i*2)) 52 { 53 for (;top;top--) vis[sta[top]]=0; 54 if (!dfs(i*2+1)) return 0; 55 } 56 } 57 return 1; 58 } 59 }G; 60 struct Point 61 { 62 int x,y; 63 }a[maxn]; 64 double dis[maxn][maxn]; 65 #define eps 1e-5 66 double sqr(double x) {return x*x;} 67 double caldis(int p,int q) 68 { 69 return sqrt(sqr(a[p].x-a[q].x)+sqr(a[p].y-a[q].y)); 70 } 71 bool judge(double x) 72 { 73 for (int i=1;i<=n;i++) 74 for (int j=i+1;j<=n;j++) 75 { 76 if (dis[i*2][j*2]<x*2) G.add_clause(i*2+1,j*2+1); 77 if (dis[i*2+1][j*2]<x*2) G.add_clause(i*2,j*2+1); 78 if (dis[i*2][j*2+1]<x*2) G.add_clause(i*2+1,j*2); 79 if (dis[i*2+1][j*2+1]<x*2) G.add_clause(i*2,j*2); 80 } 81 return G.twosat(); 82 } 83 int main() 84 { 85 while (~scanf("%d",&n)) 86 { 87 for (int i=1;i<=n;i++) 88 scanf("%d%d%d%d",&a[i*2].x,&a[i*2].y,&a[i*2+1].x,&a[i*2+1].y); 89 double L=0.0,R=0.0; 90 for (int i=2;i<=n*2+1;i++) 91 for (int j=2;j<=n*2+1;j++) 92 dis[i][j]=caldis(i,j),R=max(R,dis[i][j]); 93 while (R-L>=eps) 94 { 95 G.clear(); 96 double mid=(L+R+eps)/2; 97 if (judge(mid)) L=mid; 98 else R=mid-eps; 99 } 100 printf("%.2lf ",L); 101 } 102 return 0; 103 }