ZOJ 3717 - Balloon 简单二分+2-sat..精度恶心..

21 篇文章 0 订阅

           题意:

                   在一个三维空间中..可以放气球..每次给两个气球..必须并且仅可放一个气球..现在要求所放气球都没有冲突..请求出最长的半径是多少..

           题解:

                   一看就是2-sat+二分了..和HDU 3622一回事...WA了好多发..原因是输出的精度..吐..

Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<set>
#include <stack>
#include<queue>
#include<algorithm>
#include<cmath>
#define eps 1e-4
#define oo 1000000007
#define MAXN 505
#define ll long long
#define pi acos(-1.0) 
using namespace std;  
struct NODE
{
      int x,y,z;
}P[MAXN];
struct node
{
      int v,next;
}edge[MAXN*MAXN];
int Ne,_next[MAXN],dfn[MAXN],low[MAXN],DfsIndex,tp[MAXN],tpnum;
bool inS[MAXN];
stack<int> S;
double dis[MAXN][MAXN];
void addedge(int u,int v)
{
      edge[++Ne].next=_next[u],_next[u]=Ne,edge[Ne].v=v;
}
void tarjan(int u)
{
      int k,v;
      dfn[u]=low[u]=++DfsIndex;
      inS[u]=true,S.push(u);
      for (k=_next[u];k;k=edge[k].next)
      {
               v=edge[k].v;
               if (!dfn[v])
               {
                     tarjan(v);
                     low[u]=min(low[u],low[v]);
               }else
               if (inS[v])
                     low[u]=min(low[u],dfn[v]);
      }
      if (dfn[u]==low[u])
      {
               tpnum++;
               do
               {
                      u=S.top(),S.pop();
                      inS[u]=false;
                      tp[u]=tpnum;
               }while (dfn[u]!=low[u]);
      }
}
bool ok(int n,double d)
{
      int i,j;
      Ne=0,memset(_next,0,sizeof(_next));
      for (i=0;i<n<<1;i++)
          for (j=i+1;j<n<<1;j++)
              if (dis[i][j]<d) addedge(i,j^1),addedge(j,i^1);
      memset(dfn,0,sizeof(dfn));
      memset(inS,false,sizeof(inS));
      while (!S.empty()) S.pop();
      DfsIndex=tpnum=0;
      for (i=0;i<n<<1;i++)
         if (!dfn[i]) tarjan(i);
      for (i=0;i<n;i++)
         if (tp[i<<1]==tp[i<<1|1]) return false;
      return true;
}
int main()
{           
      int n,i,j;
      double l,r,mid;
      while (~scanf("%d",&n))
      {
             for (i=0;i<n;i++) 
                 scanf("%d%d%d",&P[i<<1].x,&P[i<<1].y,&P[i<<1].z),
                 scanf("%d%d%d",&P[i<<1|1].x,&P[i<<1|1].y,&P[i<<1|1].z);
             for (i=0;i<n<<1;i++) 
                 for (j=0;j<n<<1;j++)
                     dis[i][j]=sqrt((P[i].x-P[j].x)*(P[i].x-P[j].x)
                                   +(P[i].y-P[j].y)*(P[i].y-P[j].y)
                                   +(P[i].z-P[j].z)*(P[i].z-P[j].z));
             l=0,r=oo;
             while (r-l>eps)
             {
                     mid=(r+l)/2;
                     if (ok(n,mid*2)) l=mid;
                                 else r=mid;
             }
             printf("%.3lf\n",l-0.0005);
      }
      return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值