zoukankan      html  css  js  c++  java
  • hdu3622 2-sat问题,二分+判断有无解即可。

    /*2-sat问题初破!题意:每一对炸弹只能选一个(明显2-sat),每个炸弹半径自定,爆炸范围不可
    相交,求那个最小半径的最大值(每种策略的最小半径不同)。思:最优解:必然是选择的点最近
    的俩个距离/2,其他半径大小无纺,不妨设他们都为该最小半径。求最小值最大,二分答案,每次判定
    R是否可行,可行就往大的搜索,注意精度r-l<10^-4才可过。该题不需要输出方案,只需判定是否矛盾的

    点在同一个SCC中即可。*/

    #include<iostream>  //G++ 343ms,/c++,898ms 不知道为神马。。。求解释。。
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<stack>
    #include<cmath>
    using namespace std;
    int n;const int MAX=201;
    struct points   //点,01,23,45.。。相连为一对,x^1取对应点(改变奇偶性)
    {
        int x,y;
    };
    points  point[MAX];
    int low[MAX];int dfn[MAX];int visited[MAX];bool is_instack[MAX];stack<int>s;
    int times=0; int scc[MAX]; int numblock;
    vector<vector<int> >edges(MAX);  //原图
    void initialize()         //初始化要注意!看哪里新建图,新遍历了。因为它耽误了好久!
    {
        numblock=times=0;
        for(int i=0;i<2*n;i++)
         {
             visited[i]=low[i]=dfn[i]=is_instack[i]=0;
             edges[i].clear();
             scc[i]=-1;
         }
    }
    void tarjan(int u)    //有向图dfs,这个不解释
    {
        low[u]=dfn[u]=++times;
        is_instack[u]=1;
        s.push(u);
        int len=edges[u].size();
          for(int i=0;i<len;i++)
          {
              int v=edges[u][i];
              if(visited[v]==0)
               {
                   visited[v]=1;
                   tarjan(v);
                   if(low[u]>low[v])low[u]=low[v];
               }
               else if(is_instack[v]&&dfn[v]<low[u])
               {
                   low[u]=dfn[v];
               }
          }
         if(dfn[u]==low[u])
         {
              numblock++;
             int cur;
             do
             {
                 cur=s.top();
                 is_instack[cur]=0;
                 s.pop();
                 scc[cur]=numblock;
             }while(cur!=u);
         }
    }
    double dis(points a,points b)  //距离的平方,比较平方即可(据说更精准)。
    {
        double temp=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
        return (temp);
    }
    bool check(double r)        
    {
         initialize();  //哪里初始化很重要!
        for(int i=0;i<2*n;i++)     //根据r建图
          for(int j=i+1;j<2*n;j++)
          {
              if(((i>>1)!=(j>>1))&&dis(point[i],point[j])<4*r*r)   //这里的读入很妙(学来的),等价偶数枚举其大2之后的,奇数枚举其后(比他大1)所有
                 {
                       edges[i].push_back(j^1);
                       edges[j].push_back(i^1);
                 }
          }
         for(int i=0;i<2*n;i++)          
           {
               if(visited[i]==0)
                 {
                     visited[i]=1;
                     tarjan(i);
                 }
           }
         for(int i=0;i<2*n;i+=2)     
         {
           if(scc[i]==scc[i+1])  //矛盾的点在一个SCC中,
            {
                return false;
            }
         }
         return true;
    }
    void readin()
    {
        for(int i=0;i<n;i++)
        {
           scanf("%d%d%d%d",&point[i*2].x,&point[i*2].y,&point[i*2+1].x,&point[i*2+1].y);
        }
    }
    int main()
    {
        while(~scanf("%d",&n))
        {
            readin();
            double r;double left=0,right=10001,mid;
            while(right-left>0.0001)      //二分答案!
            {
                mid=(right+left)/2;
                if(check(mid))
                {
                    left=mid; 
                }
                else
                {
                    right=mid;
                }
            }
            printf("%.2f
    ",left);
        }
    }
    


  • 相关阅读:
    Censored! POJ
    POJ
    HDU
    ionic中的生命周期函数
    ionic项目相关的操作命令
    数组的join()函数操作
    pop()实现逐个删除数组最后一位并输出
    CSS制作彩虹效果
    ionic2 页面加载时图片添加的问题
    升级ionic版本后,创建新项目报Error Initializing app错误解决
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925812.html
Copyright © 2011-2022 走看看