题目:给出空间中的n对点,要求从每对点中选出一个,使得最近的点的距离最远。
分析:
二分的思想很明显,二分答案之后,建图:如果两点之间的距离小于二分值时,连接相应的边,通过2-sat判断一下即可。
注意到题目的要求是向下取整,于是我们可以先*10000,最后直接取模即可。
#include <set> #include <map> #include <list> #include <cmath> #include <queue> #include <stack> #include <string> #include <vector> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; #define debug puts("here") #define rep(i,n) for(int i=0;i<n;i++) #define rep1(i,n) for(int i=1;i<=n;i++) #define REP(i,a,b) for(int i=a;i<=b;i++) #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++) #define pb push_back #define RD(n) scanf("%d",&n) #define RD2(x,y) scanf("%d%d",&x,&y) #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w) #define All(vec) vec.begin(),vec.end() #define MP make_pair #define PII pair<int,int> #define PQ priority_queue #define cmax(x,y) x = max(x,y) #define cmin(x,y) x = min(x,y) #define Clear(x) memset(x,0,sizeof(x)) /******** program ********************/ const int MAXN = 405; const int MAXM = 1000005; int low[MAXN],sta[MAXN],dfn[MAXN],fa[MAXN],dep,bcnt,top; bool use[MAXN]; int po[MAXN],tol,n,m; struct Edge { int y,next; } edge[MAXM]; struct Point { int a[3]; void rd() { RD3(a[0],a[1],a[2]); a[0] *= 10000; a[1] *= 10000; a[2] *= 10000; } } p[MAXN][2]; void add(int x,int y) { edge[++tol].y = y; edge[tol].next = po[x]; po[x] = tol; } void dfs(int x) { sta[++top] = x; use[x] = true; low[x] = dfn[x] = ++ dep; int y; for(int i=po[x]; i; i=edge[i].next) { y = edge[i].y; if(!dfn[y]) { dfs(y); low[x] = min(low[x],low[y]); } else if(use[y]) low[x] = min(low[x],dfn[y]); } if(low[x]==dfn[x]) { ++ bcnt; do { y = sta[top--]; use[y] = false; fa[y] = bcnt; } while(x!=y); } } bool sat() { memset(dfn,0,sizeof(dfn)); memset(use,false,sizeof(use)); dep = top = bcnt = 0; rep1(i,2*n) if(!dfn[i]) dfs(i); rep1(i,n) if(fa[i]==fa[i+n]) return false; return true; } ll sqr(ll x) { return x*x; } ll dist(Point a,Point b) { return sqr(a.a[0]-b.a[0])+sqr(a.a[1]-b.a[1])+sqr(a.a[2]-b.a[2]); } bool solve(ll mid) { memset(po,0,sizeof(po)); tol = 0; rep1(i,n) { rep1(j,n) { if(i==j)continue; ll d = dist(p[i][0],p[j][0]); if(d<mid) { add(i,j+n); add(j,i+n); } d = dist(p[i][0],p[j][1]); if(d<mid) { add(i,j); add(j+n,i+n); } d = dist(p[i][1],p[j][0]); if(d<mid) { add(i+n,j+n); add(j,i); } d = dist(p[i][1],p[j][1]); if(d<mid) { add(i+n,j); add(j+n,i); } } } return sat(); } int main() { #ifndef ONLINE_JUDGE freopen("sum.in", "r", stdin); // freopen("cf.out", "w", stdout); #endif while(~RD(n)) { rep1(i,n) { p[i][0].rd(); p[i][1].rd(); } ll ans = -1 , l = 0 , r = 2000000000LL; while(l<=r) { ll mid = (l+r)/2; if(solve(mid*mid)) { l = mid+1; ans = mid; } else r = mid-1; } printf("%lld.%03lld\n",ans/20000,(ans/2%10000)/10 ); } return 0; }