HDU3622 Bomb Game(二分+2-SAT)

题意

给n对炸弹可以放置的位置(每个位置为一个二维平面上的点),
每次放置炸弹是时只能选择这一对中的其中一个点,每个炸弹爆炸
的范围半径都一样,控制爆炸的半径使得所有的爆炸范围都不相
交(可以相切),求解这个最大半径.

题解

首先二分最大半径值,然后2-sat构图判断其可行性,
对于每 两队位置(u,uu)和(v,vv),如果u和v之间的距离小于2*id,
也就是说位置u和位置v处不能同时防止炸弹(两范围相交),
所以连边(u,vv) 和(v,uu),求解强连通分量判断可行性.
注意精度问题

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;
#define debug(x) cout << "fuck bug " << x << "
";
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int maxn = 4e4 + 7;
const double eps = 0.00000001;
typedef long long ll;

int n,m;

struct edge
{
    int to,nxt;
}e[maxn];//,eg[maxn];


int head[maxn],tot;//int head2[maxn],tot2;

void add(int u ,int v){
    e[++tot].to = v;
    e[tot].nxt = head[u];
    head[u] = tot;
    // eg[++tot2].to = v;
    // eg[tot2].nxt = head2[u];
    // head2[u] = tot2;
}




int dfn[maxn],low[maxn],num,inStack[maxn];
int stack[maxn],top,cnt,C[maxn];
void tarjan(int x) {
    dfn[x] = low[x] = ++num;
    stack[++top] = x; inStack[x] = true;
    for (int i = head[x]; i; i = e[i].nxt) {
        int y = e[i].to;
        if (dfn[y] == 0) {
            tarjan(y);
            low[x] = min(low[x], low[y]);
        } else if (inStack[y]) {
            low[x] = min(low[x], low[y]);
        }
    }
    if (low[x] == dfn[x]) {
        cnt++;
        int z;
        do {
            z = stack[top--];
            inStack[z] = false;
            C[z] = cnt;
        } while (z != x);
    }
}

struct Point
{
    double x,y;
}P[maxn];

double dis(Point a,Point b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

void init(){
    memset(head,0,sizeof head);
    memset(e,0,sizeof e);
    //memset(head2,0,sizeof head2);
    memset(dfn,0,sizeof dfn);
    //memset(vis2,0,sizeof vis2);
    //tot2 = tot = 0;
    //cnt1 = cnt = 0;
    tot = top = cnt = num = 0 ;
    memset(C,0,sizeof C);
}

int main(int argc, char const *argv[])
{
    int n;
    while(~scanf("%d",&n)){
        for(int i = 0;i < n + n;i += 2){
            scanf("%lf %lf %lf %lf",&P[i].x,&P[i].y,&P[i^1].x,&P[i^1].y);
        }
        double l = 0,r = 40000;
        double ans = -1;
        while(r - l > eps){
            double mid = (l + r) / 2;
            init();
            for(int i = 0;i < n + n; i += 2){
                for(int j = i + 2;j < n + n;j ++){
                    if(dis(P[i],P[j]) < 2 * mid){
                        add(i,j^1);
                        add(j,i^1);
                    }
                }
            }

            for(int i = 1;i < n + n;i += 2){
                for(int j = i + 1;j < n + n;j ++){
                    if(dis(P[i],P[j]) < 2 * mid){
                        add(i,j^1);
                        add(j,i^1);
                    }
                }
            }

            for(int i = 0;i < n + n;i ++){
                if(!dfn[i]) tarjan(i);
            }

            bool flag = 1;
            for(int i = 0;i < n + n;i += 2){
                if(C[i] == C[i + 1]){
                    flag = 0;
                    break;
                }
            }

            if(flag){
                l = mid;
                ans = mid;
            }else{
                r = mid;
            }
        }
        printf("%.2lf
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/DWVictor/p/11355022.html