大意:给定X、Y定圆,一次只能选一个,圆之间不能互相冲突,问:最大的满足条件的半径是多少?

思路:二分半径,2-SAT判断是否满足条件。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <map>
using namespace std;

const int maxn = 210;
const int maxm = 210*210*2;

struct Edge
{
    int v, w;
    int next;
    int id;
}edge[maxm];

int first[maxn], stack[maxn], ins[maxn], dfn[maxn], low[maxn];
int belong[maxn];

int n, m;
int cnt;
int scnt, top, tot;

void init()
{
    cnt = 0;
    scnt = top = tot = 0;
    memset(first, -1, sizeof(first));
    memset(dfn, 0, sizeof(dfn));
    memset(ins, 0, sizeof(ins));
    memset(low, 0, sizeof(low));
}

void read_graph(int u, int v)
{
    edge[cnt].v = v;
    edge[cnt].next = first[u], first[u] = cnt++;
}

void dfs(int u)
{
    int v;
    low[u] = dfn[u] = ++tot;
    stack[top++] = u;
    ins[u] = 1;
    for(int e = first[u]; e != -1; e = edge[e].next)
    {
        v = edge[e].v;
        if(!dfn[v]) { dfs(v); low[u] = min(low[u], low[v]); }
        else if(ins[v]) { low[u] = min(low[u], dfn[v]); }
    }
    if(low[u] == dfn[u])
    {
        scnt++;
        do { v = stack[--top]; belong[v] = scnt; ins[v] = 0; } while(u != v);
    }
}

void Tarjan()
{
    for(int v = 0; v < 2*n; v++) if(!dfn[v])
        dfs(v);
}

void readint(int &x)
{
    char c;
    while(!isdigit(c)) c = getchar();
    
    x = 0;
    while(isdigit(c))
    {
        x = x*10 + c-'0';
        c = getchar();
    }
}

void writeint(int x)
{
    if(x > 9) writeint(x/10);
    putchar(x%10+'0');
}

struct Point
{
    double x, y;
    
    Point(double x=0, double y=0): x(x), y(y) {}
};

Point P[maxn];

double L, R;

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

double dist[maxn][maxn];

const double INF = 1e60;
const double eps = 1e-6;

void read_case()
{
    double x1, y1, x2, y2;
    L = INF, R = -INF;
    
    for(int i = 0; i < n; i++)
    {
        scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
        P[i] = Point(x1, y1), P[i+n] = Point(x2, y2);
    }
    
    for(int i = 0; i < 2*n; i++)
    for(int j = i+1; j < 2*n; j++)
    {
        dist[i][j] = dist[j][i] = Dist(P[i], P[j]);
        L = min(L, dist[i][j]), R = max(R, dist[i][j]);
    }
}

int check()
{
    for(int i = 0; i < n; i++) if(belong[i] == belong[n+i]) return 0;
    return 1;
}

void build(double mid)
{
    init();
    for(int i = 0; i < 2*n; i++)
    {
        for(int j = 0; j < 2*n; j++) if(i != j)
        {
            if(dist[i][j] < 2*mid) //圆心距小于半径*2
            {
                if(i < n && j < n)
                {
                    read_graph(i, j+n);
                    read_graph(j, i+n);
                }
                else if(i < n && j >= n)
                {
                    read_graph(i, j-n);
                    read_graph(j, i+n);
                }
                else if(i >= n && j < n)
                {
                    read_graph(i, j+n);
                    read_graph(j, i-n);
                }
                else
                {
                    read_graph(i, j-n);
                    read_graph(j, i-n);
                }
            }
        }
    }
    
    Tarjan();
}

double BSearch()
{
    double ans = 0;
    L /= 2, R /= 2;
    while(R-L >= eps)
    {
        double mid = L+(R-L)/2;
        build(mid);
        if(check()) L = mid;
        else R = mid;
    }
    return L;
}

void solve()
{
    read_case();
    double ans = BSearch();
    printf("%.2lf\n", ans);
}

int main()
{
    while(~scanf("%d", &n))
    {
        solve();
    }
    return 0;
}
View Code

 

posted on 2013-06-08 12:36  Buck Meister  阅读(150)  评论(0编辑  收藏  举报