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\n",ans);
 96      if(n==k){printf("+INF\n");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\n",ans);
107     return 0;
108 }

 

posted @ 2018-03-26 10:50  CHerish_OI  阅读(235)  评论(0编辑  收藏  举报