zoukankan      html  css  js  c++  java
  • bzoj2663: [Beijing wc2012]灵魂宝石(二分+匈牙利)

    2663: [Beijing wc2012]灵魂宝石

    题目:传送门 


    题解:

       又是一道卡精度的题目。

       很容易就可以看出单调性啊,如果R越大,选的人就越多,R越小,选的人就越少。

       那最小值就直接搞咯。

       那么对于最大值...n==k肯定就是无限大啦

       否则的话...有点恶心...太菜了

       我们换个角度想问题,因为要知道R的最大值,那么在只能选择k个人的情况下,我们只需要知道n-k个人的最大匹配的最小R值就好。

       那么反过来,原本是距离<R时建边,现在就改为距离>=R时再建边。。。

       精度1e-7...

        


    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cmath>
      5 #include<algorithm>
      6 #define eps 1e-7
      7 using namespace std;
      8 struct node
      9 {
     10     double x,y,next;
     11 }a[25000];int len,last[25000];
     12 void ins(int x,int y)
     13 {
     14     len++;a[len].x=x;a[len].y=y;
     15     a[len].next=last[x];last[x]=len;
     16 }
     17 int match[25000],chw[25000],t;
     18 bool findmuniu(int x)
     19 {
     20     for(int k=last[x];k;k=a[k].next)
     21     {
     22         int y=a[k].y;
     23         if(chw[y]!=t)
     24         {
     25             chw[y]=t;
     26             if(match[y]==0 || findmuniu(match[y]))
     27             {
     28                 match[y]=x;
     29                 return true;
     30             }
     31         }
     32     }
     33     return false;
     34 }
     35 struct dian
     36 {
     37     double x,y;
     38 }b[25000];
     39 struct bs
     40 {
     41     double x,y;
     42 }c[25000];
     43 int n,k;
     44 double dis(double x1,double y1,double x2,double y2){return sqrt(abs((x1-x2)*(x1-x2))+abs((y1-y2)*(y1-y2)));}
     45 int check(double R,int opt)
     46 {
     47     int ans=0;
     48     len=0;memset(last,0,sizeof(last));
     49     if(opt==1)
     50     {
     51         for(int i=1;i<=n;i++)
     52             for(int j=1;j<=n;j++)
     53                 if(dis(b[i].x,b[i].y,c[j].x,c[j].y)<R)
     54                     ins(i,j+n);
     55         memset(match,0,sizeof(match));
     56         memset(chw,0,sizeof(chw));t=0;ans=0;
     57         for(int i=1;i<=n;i++)
     58         {
     59             t++;
     60             if(findmuniu(i))
     61                 ans++;
     62         }
     63     }
     64     else
     65     {
     66         for(int i=1;i<=n;i++)
     67             for(int j=1;j<=n;j++)
     68                 if(dis(b[i].x,b[i].y,c[j].x,c[j].y)>=R)
     69                     ins(i,j+n);
     70         memset(match,0,sizeof(match));
     71         memset(chw,0,sizeof(chw));t=0;ans=0;
     72         for(int i=1;i<=n;i++)
     73         {
     74             t++;
     75             if(findmuniu(i))
     76                 ans++;
     77         }
     78     }
     79     return ans;
     80 }
     81 int main()
     82 {
     83      scanf("%d%d",&n,&k);
     84      for(int i=1;i<=n;i++)scanf("%lf%lf",&b[i].x,&b[i].y);
     85      for(int i=1;i<=n;i++)scanf("%lf%lf",&c[i].x,&c[i].y);
     86      double l=0.0,r=999999999.9,ans;
     87      while(r-l>=eps)
     88     {
     89          double mid=(l+r)/2.0;
     90          int tt=check(mid,1);
     91          if(tt==k)ans=mid;
     92          if(tt>=k)r=mid-eps;
     93          else l=mid+eps;
     94      }
     95      printf("%.2lf
    ",ans);
     96      if(n==k){printf("+INF
    ");return 0;}
     97      l=0.0,r=999999999.9,ans=0.0;
     98      while(r-l>=eps)
     99      {
    100          double mid=(l+r)/2.0;
    101          int tt=check(mid,2);
    102          if(tt==n-k)ans=mid;
    103          if(tt<n-k)r=mid-eps;
    104          else l=mid+eps;
    105      }
    106      printf("%.2lf
    ",ans);
    107     return 0;
    108 }
  • 相关阅读:
    psacct监视用户执行的命令,如cpu时间和内存战胜,实时进程记账
    iostat,mpstat,sar即时查看工具,sar累计查看工具
    sysstat服务负载统计,如CPU占有率,网络使用率,磁盘速度
    linux top命令VIRT,RES,SHR,DATA的含义
    lsof查看进程打开了哪些文件目录套接字
    linux系统监控常用工具
    Linux系统维护修复模式
    centos单用户模式:修改ROOT密码和grub加密
    Linux系统启动过程介绍
    Android原生APP内分享
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8649470.html
Copyright © 2011-2022 走看看