bzoj2663: [Beijing wc2012]灵魂宝石

二分+匈牙利,min问题不大,对于max询问,把他视作最坏情况,那么不匹配的要尽量多,二分图跑的是不能控制的。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps=1e-7;

int n;
struct point
{
    double x,y;
}A[110],B[110];

struct node
{
    int x,y,next;
}a[21000];int len,last[110];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
int match[110];
bool v[110];
bool findmuniu(int x)
{
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(v[y]==true)
        {
            v[y]=false;
            if(match[y]==0||findmuniu(match[y])==true)
            {
                match[y]=x;
                return true;
            }
        }
    }
    return false;
}
double dis(int i,int j){return sqrt((A[i].x-B[j].x)*(A[i].x-B[j].x)+(A[i].y-B[j].y)*(A[i].y-B[j].y));}
int check(double mid,int tp)
{
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            double d=dis(i,j);
            if(tp==1)
            {
                if(abs(d-mid)<=eps||d<mid)ins(i,j);
            }
            else
            {
                if(abs(d-mid)<=eps||d>mid)ins(i,j);
            }
        }
    memset(match,0,sizeof(match));
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        memset(v,true,sizeof(v));
        if(findmuniu(i)==true)ans++;
    }
    return ans;
}
int main()
{
    int K;
    scanf("%d%d",&n,&K);
    for(int i=1;i<=n;i++)scanf("%lf%lf",&A[i].x,&A[i].y);
    for(int i=1;i<=n;i++)scanf("%lf%lf",&B[i].x,&B[i].y);
    
    double l,r;
    
    double mmin;
    l=0,r=999999999.9;
    while((r-l)>eps)
    {
        double mid=(l+r)/2;
        int d=check(mid,1);
        if(d<K)l=mid+eps;
        else if(d>K)r=mid-eps;
        else
        {
            r=mid-eps;
            mmin=mid;
        }
    }
    
    double mmax;
    if(n==K){printf("%.2lf +INF\n",mmin);return 0;}
    l=0,r=999999999.9;
    while((r-l)>eps)
    {
        double mid=(l+r)/2;
        int d=check(mid,2);
        if(d<n-K)r=mid-eps;
        else if(d>n-K)l=mid+eps;
        else
        {
            l=mid+eps;
            mmax=mid;
        }
    }
    printf("%.2lf %.2lf\n",mmin,mmax);
    return 0;
}

 

posted @ 2018-03-23 13:34  AKCqhzdy  阅读(132)  评论(0编辑  收藏  举报