题意:

有N组炸弹,2*i与2*i+1为一组,从这N组炸弹中选N个炸弹放入格子中,

要求:1.同组的炸弹不能同时放入;2.放入的炸弹不能相互引爆;3.每个炸弹有相同的半径;

让你求半径里最短中最长的。

思路:

二分答案,用2-SAT判可行性。加边时,凡是可以互相引爆的两个点互斥。

注意:

对double型二分。引入eps.

View Code
/*
Problem:3622 (Bomb Game) Judge Status:Accepted
RunId:6286747 Language:G++ Author:2010201211
Time:578MS Memory:2172K Len:3830B
*/
#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
#include <string.h>
#define E 1000050
#define V 1000
#define eps 1e-8
double d[V][V];
int n;
double minc,maxc;
struct Zu
{
    double x1,y1,x2,y2;
}zu[105];

/******************2-SAT*********************/
int top,cnt,index,ecnt;
bool instack[V];
int stack[V],id[V],dfn[V],low[V];
int head[V];
struct edge{
    int s,t,next;
}e[E];
void addedge(int u,int v){
    e[ecnt].s=u;
    e[ecnt].t=v;
    e[ecnt].next=head[u];
    head[u]=ecnt++;
}
void tarjan(int u){
    int v;
    int tmp;
    dfn[u]=low[u]=++index;
    instack[u]=true;
    stack[++top]=u;
    for(int k=head[u];k!=-1;k=e[k].next){
        v=e[k].t;
        if(!dfn[v]){
            tarjan(v);
            if(low[v]<low[u]){
                low[u]=low[v];
            }
        }
        else if(instack[v] && dfn[v] < low[u]){
            low[u]=dfn[v];
        }
    }
    if(dfn[u]==low[u]){
        cnt++;
        do{
            tmp=stack[top--];
            instack[tmp]=false;
            id[tmp]=cnt;
        }while(tmp!=u);
    }
}
void solve(){
    top = cnt = index = 0;
    memset(dfn,0,sizeof(dfn));
    for(int i=0;i<2*n;i++){
        if(!dfn[i])
            tarjan(i);
    }
}
bool Two_Sat(){
    solve();
    for(int i=0;i<n;i++){
        if(id[i]==id[i+n]){
            return 0;
        }
    }
    return 1;
}
/******************2-SAT*********************/
/*******************dist**********************/
double dis(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
void Count_dist(){
    minc=0x3F3F3F3F,maxc=-1;
    for(int i=0;i<n;i++){
        for(int j=0;j<i;j++){
            d[i][j]=d[j][i]=dis(zu[i].x1,zu[i].y1,zu[j].x1,zu[j].y1);
            minc=min(minc,d[i][j]);
            maxc=max(maxc,d[i][j]);
            d[i][j+n]=d[j+n][i]=dis(zu[i].x1,zu[i].y1,zu[j].x2,zu[j].y2);
            minc=min(minc,d[i][j+n]);
            maxc=max(maxc,d[i][j+n]);
            d[i+n][j]=d[j][i+n]=dis(zu[i].x2,zu[i].y2,zu[j].x1,zu[j].y1);
            minc=min(minc,d[i+n][j]);
            maxc=max(maxc,d[i+n][j]);
            d[i+n][j+n]=d[j+n][i+n]=dis(zu[i].x2,zu[i].y2,zu[j].x2,zu[j].y2);
            minc=min(minc,d[i+n][j+n]);
            maxc=max(maxc,d[i+n][j+n]);
        }
    }
}
/*******************dist**********************/
/******************build**********************/
bool build(double r){
    ecnt=0;
    memset(head,-1,sizeof(head));
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            if(d[i][j]+eps<2*r){
                addedge(i,j+n);
                addedge(j,i+n);
            }
            if(d[i][j+n]+eps<2*r){
                addedge(i,j);
                addedge(j+n,i+n);
            }
            if(d[i+n][j]+eps<2*r){
                addedge(i+n,j+n);
                addedge(j,i);
            }
            if(d[i+n][j+n]+eps<2*r){
                addedge(i+n,j);
                addedge(j+n,i);
            }
        }
    }
    return Two_Sat();
}
/******************build**********************/
/*************2-Search******************/
void T_search(){
    double mid,l=-1,r=1000000,ans=0;
    while(r-l>=eps){
        mid=(l+r)/2.0;
        if(build(mid)){
            l=mid;
            ans=mid;
        }
        else
        {
            r=mid;
        }
    }
    printf("%.2lf\n",ans);
}
/*************2-Search******************/
int main()
{
    //freopen("in.txt","r",stdin);
    while(cin >> n){
        for(int i=0;i<n;i++){
            cin >> zu[i].x1 >> zu[i].y1 >> zu[i].x2 >> zu[i].y2;
        }
        Count_dist();
        T_search();
    }
    return 0;
}