HDOJ3622-2SAT,二分

来源:互联网 发布:软件企业认定 招标 编辑:程序博客网 时间:2024/04/30 06:30
#include <cstdio>#include <cstring>#include <iostream>#include <cmath>#include <algorithm>#include <vector>using namespace std;const int NN=210;         //之前把NN设为了100+导致RE,实在不应该const double eps=0.0001;  //精度极小值应设为输出要求精度的%1,WA在这一次struct Edge{    int v,next;}edge[400000];double x[NN],y[NN];double d[NN][NN];int head[NN];int n,ecnt,bcnt,depth,top;int dfn[NN],low[NN],belong[NN],stack[NN];bool instack[NN];void init(){    ecnt=0;    for (int i=1; i<=2*n; i++) head[i]=-1;    bcnt=0; depth=0; top=0;    for (int i=1; i<=n*2; i++)    {        dfn[i]=0;        instack[i]=false;    }}void addedge(int u,int v){    edge[ecnt].v=v;    edge[ecnt].next=head[u];    head[u]=ecnt++;}double dis(int i,int j){    return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));}void tarjan(int u)  //照着模板抄的{    dfn[u]=low[u]=++depth;    stack[++top]=u;    instack[u]=true;    int v;    for (int i=head[u]; i!=-1; i=edge[i].next)    {        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 (low[u]==dfn[u])    {        bcnt++;        do        {            v=stack[top--];            belong[v]=bcnt;            instack[v]=false;        }while (v!=u);    }}bool two_sat(double r2){      init();    for (int i=1; i<=n; i++)    {        for (int j=1; j<=n; j++)        {            if (i==j) continue;            //事实是不等式与边的关系还是没理解透,尤其不能理解图的方向性,不过i,j取值均为1~n,这里同时加了同一条边的两个方向这个不难理解            if (d[i][j]-r2<eps) addedge(i,j+n);//addedge(j,i+n);            if (d[i][j+n]-r2<eps) addedge(i,j);//addedge(j+n,i+n);            if (d[i+n][j]-r2<eps) addedge(i+n,j+n);//addedge(j,i);            if (d[i+n][j+n]-r2<eps) addedge(i+n,j);//addedge(j+n,i);        }    }    for (int i=1; i<=2*n; i++)      if (!dfn[i]) tarjan(i);    for (int i=1; i<=n; i++)    {        if (belong[i]==belong[i+n]) return false;    }    return true;}int main(){    while (scanf("%d",&n)!=EOF)    {        init();        for (int i=1; i<=n; i++) scanf("%lf%lf%lf%lf",&x[i],&y[i],&x[i+n],&y[i+n]);        double mm=0;        for (int i=1; i<=n*2; i++)          for (int j=1; j<=n*2; j++)          {              d[i][j]=dis(i,j);              if (d[i][j]>mm) mm=d[i][j];          }        double l=0.0;        double r=mm;        double mid;        while (r-l>eps)  //浮点数的二分比整数好写多了        {            mid=(l+r)/2;            if (two_sat(mid*2)) l=mid;            else              r=mid;        }        printf("%.2f\n",mid);    }    return 0;}