HDU 3622 Bomb Game (Binary + 2-SAT), hdu2-sat
Address: HDU 3622
Divide the radius into two points first, and then add edges to those points that cannot be selected if they are smaller than the radius. Then determine the feasibility.
The Code is as follows:
#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <stdlib.h>#include <math.h>#include <ctype.h>#include <queue>#include <map>#include <set>#include <algorithm>using namespace std;#define LL __int64const int INF=0x3f3f3f3f;const double eqs=1e-3;int head[410], cnt, top, ans, index;int dfn[410], low[410], instack[410], stak[410], belong[410];struct node{ int u, v, next;}edge[1000000];struct Point{ int x, y;}dian[10000];void add(int u, int v){ edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++;}void tarjan(int u){ dfn[u]=low[u]=++index; instack[u]=1; stak[++top]=u; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v]) { low[u]=min(low[u],dfn[v]); } } if(dfn[u]==low[u]) { ans++; while(1) { int v=stak[top--]; instack[v]=0; belong[v]=ans; if(u==v) break; } }}void init(){ memset(head,-1,sizeof(head)); cnt=0; memset(dfn,0,sizeof(dfn)); memset(instack,0,sizeof(instack)); top=ans=index=0;}double dist(Point x, Point y){ return sqrt((x.x-y.x)*(x.x-y.x)*1.0+(x.y-y.y)*(x.y-y.y));}int solve(double mid, int n){ int i, j; init(); for(i=0;i<n<<1;i++) { for(j=0;j<i;j++) { if(dist(dian[i],dian[j])<mid) { add(i,j^1); add(j,i^1); //add(j^1,i); //add(i^1,j); //printf("%d %d %d %d\n",i<<1,j<<1|1,j<<1,i<<1|1); } } } for(i=0;i<n<<1;i++) { if(!dfn[i]) tarjan(i); } for(i=0;i<n;i++) { if(belong[i<<1]==belong[i<<1|1]) return 0; } return 1;}int main(){ int n, i, j; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;i++) { scanf("%d%d%d%d",&dian[i<<1].x,&dian[i<<1].y,&dian[i<<1|1].x,&dian[i<<1|1].y); } double r=40000.0, l=0, mid, ans; while(r-l>eqs) { mid=(l+r)/2; //printf("%.2lf\n",mid); if(solve(mid, n)) { ans=mid; l=mid; } else r=mid; } printf("%.2lf\n",ans/2.0); } return 0;}