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; }
pain and happy in the cruel world.