2-SAT好题hdu-3622

来源:互联网 发布:在淘宝上买了二手钢琴 编辑:程序博客网 时间:2024/05/17 18:43

题目链接


http://acm.hdu.edu.cn/showproblem.php?pid=3622
 题意为给定n组坐标每组坐标有两个坐标,每组坐标中只能选择一个坐标,以每个选定坐标画圆,并且任意两个圆不相交,问最小半径的最大值是多少。
 题目给的2-sat很裸,但是并不能贪心得到每次半径值,最后看了大牛的题解,直接二分答案,每次求一次2-sat判断即可,至此就是水题了。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <stack>#include <queue>#include <cmath>#define inf 0x3f3f3f3f#define rep(i, s, t) for(int i = s;i <= t;i++)#define rap(i, s, t) for(int i = s;i >= t;i--)using namespace std;int n;const double eps = 1e-7;struct Edge{    int v;    int next;}edge[1000004];struct node{    double x, y;}s[1005];int head[1005];int cnt_edge;void init(){    memset(head, -1, sizeof(head));    cnt_edge = 0;}double d(node a, node b){    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));}void add_Edge(int u, int v){    edge[cnt_edge].v = v;    edge[cnt_edge].next = head[u];    head[u] = cnt_edge++;}void get_Map(double mid){    rep(i, 0, n - 1){        rap(j, i - 1, 0){            if(d(s[i<<1], s[j<<1]) - mid * 2 < eps)                add_Edge(i<<1, j<<1^1), add_Edge(j <<1, i<<1^1);            if(d(s[i<<1], s[j<<1^1]) - mid * 2 < eps)                add_Edge(i <<1, j<<1),add_Edge(j <<1^1, i<<1^1);            if(d(s[i<<1^1], s[j <<1]) - mid * 2 < eps)                add_Edge(i <<1^1, j<<1^1), add_Edge(j<<1, i<<1);            if(d(s[i<<1^1], s[j<<1^1]) - mid * 2 < eps)                add_Edge(i<<1^1, j<<1),add_Edge(j<<1^1, i<<1);        }    }}int dfn[1005], low[1005];stack<int>SS;int Instack[1005];int Index;int cnt_Bcnt;int Bcnt[1005];void tarjan(int a){    low[a] = dfn[a] = Index++;    Instack[a] = 1;    SS.push(a);    for(int i = head[a];i != -1;i = edge[i].next)    {        int v = edge[i].v;        if(!dfn[v]){            tarjan(v);            low[a] = min(low[a], low[v]);        }        else{            if(Instack[v]&&dfn[v] < low[a])                low[a] = dfn[v];        }    }    if(dfn[a] == low[a])    {        int ls;        cnt_Bcnt++;        do        {            ls = SS.top();            SS.pop();            Instack[ls] = 0;            Bcnt[ls] = cnt_Bcnt;        }        while(ls != a);    }}void find_Scc(){    memset(Instack, 0, sizeof(Instack));    memset(Bcnt, 0, sizeof(Bcnt));    memset(low, 0, sizeof(low));    memset(dfn, 0, sizeof(dfn));    cnt_Bcnt = 0;    Index = 0;    rep(i, 0, 2 * n - 1)        if(!dfn[i])            tarjan(i);}int solve(){    rep(i, 0, n - 1)    {        if(Bcnt[i<<1] == Bcnt[i<<1^1])            return 0;    }    return 1;}int main(){    while(~scanf("%d", &n))    {        rep(i, 0, n - 1){            scanf("%lf%lf%lf%lf", &s[i<<1].x, &s[i<<1].y, &s[i<<1^1].x, &s[i<<1^1].y);        }        double left = 0;        double right = 20000, mid;        double ans = 0;        while(right - left > eps){            mid = (right + left) / 2;            init();            get_Map(mid);            find_Scc();            if(solve()){                ans = max(ans, mid);                left = mid;            }            else                right = mid;        }        printf("%.2f\n", ans);    }    return 0;}
原创粉丝点击