这题是二分+2SAT.
总结一下SAT题的特征。首先,可能会存在二选一的情况,然后会给出一些矛盾。据这些矛盾加边,再用SAT判定。
这一道题好像不能直接用printf("%0.3lf"),因为这个是四舍五入的,这道题好像不能四舍五入,只好选减去0.0005再按这个格式输出了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <stdlib.h> 7 #define oo 1000000007 8 #define eps 1e-4 9 using namespace std; 10 const int MAXN=420; 11 const int MAXM=320000; 12 struct b{ 13 int x,y,z; 14 }ball[MAXN]; 15 double dis[MAXN][MAXN]; 16 int head[MAXN],dfn[MAXN],low[MAXN],tot,stop,indx,belong[MAXN],pat; 17 int st[MAXN]; 18 bool stack[MAXN]; 19 int n; 20 struct e{ 21 int u,v; 22 int next; 23 }edge[MAXM]; 24 25 void addedge(int u,int v){ 26 edge[tot].u=u; 27 edge[tot].v=v; 28 edge[tot].next=head[u]; 29 head[u]=tot++; 30 } 31 32 void tarjan(int u){ 33 int v; 34 dfn[u]=low[u]=++indx; 35 st[stop++]=u; 36 stack[u]=true; 37 for (int e=head[u];e!=-1;e=edge[e].next){ 38 v=edge[e].v; 39 if (dfn[v]==0) { 40 tarjan(v) ; 41 low[u] = min(low[u], low[v]) ; 42 } 43 else if (stack[v]) { 44 low[u] = min(low[u], dfn[v]) ; 45 } 46 } 47 if (dfn[u] == low[u]) { 48 pat++; 49 do{ 50 v = st[--stop]; 51 belong[v]=pat; 52 stack[v]=false; 53 }while(u!= v); 54 } 55 } 56 57 bool slove(double leng){ 58 int a,b; tot=0; indx=0; stop=0; pat=-1; 59 memset(head,-1,sizeof(head)); 60 for(int i=0;i<n;i++){ 61 a=i; 62 for(int j=i+1;j<n;j++){ 63 b=j; 64 if(leng*2>dis[a*2][b*2]){ 65 addedge(2*a+1,b*2); 66 addedge(b*2+1,a*2); 67 } 68 if(leng*2>dis[a*2][b*2+1]){ 69 addedge(a*2+1,b*2+1); 70 addedge(b*2,a*2); 71 } 72 if(leng*2>dis[a*2+1][b*2]){ 73 addedge(a*2,b*2); 74 addedge(b*2+1,a*2+1); 75 } 76 if(leng*2>dis[a*2+1][b*2+1]){ 77 addedge(a*2,b*2+1); 78 addedge(b*2,a*2+1); 79 } 80 } 81 } 82 memset(dfn,0,sizeof(dfn)); 83 memset(low,0,sizeof(low)); 84 memset(stack,false,sizeof(stack)); 85 memset(belong,-1,sizeof(belong)); 86 for(int i=0;i<2*n;i++){ 87 if(dfn[i]==0){ 88 tarjan(i); 89 } 90 } 91 bool flag=true; 92 for(int i=0;i<n;i++){ 93 if(belong[i*2]==belong[i*2+1]){ 94 flag=false; 95 break; 96 } 97 } 98 return flag; 99 } 100 101 int main(){ 102 double xi,yi,zi; 103 while(scanf("%d",&n)!=EOF){ 104 for(int i=0;i<2*n;i++){ 105 scanf("%d%d%d",&ball[i].x,&ball[i].y,&ball[i].z); 106 i++; 107 scanf("%d%d%d",&ball[i].x,&ball[i].y,&ball[i].z); 108 } 109 double high=oo,lown=0; double tmp; 110 for(int i=0;i<2*n;i++){ 111 for(int j=i;j<2*n;j++){ 112 xi=ball[i].x-ball[j].x; 113 yi=ball[i].y-ball[j].y; 114 zi=ball[i].z-ball[j].z; 115 tmp=sqrt(xi*xi+yi*yi+zi*zi); 116 dis[i][j]=dis[j][i]=tmp; 117 } 118 } 119 double ans; 120 while(lown<high-eps){ 121 double mid=(high+lown)/2; 122 if(slove(mid)){ 123 ans=mid; 124 lown=mid; 125 } 126 else high=mid; 127 } 128 printf("%0.3lf\n",ans-0.0005); 129 } 130 return 0; 131 }