HDU+2295+Dancing+link++++二分

来源:互联网 发布:朱炫热血知乎 编辑:程序博客网 时间:2024/05/22 04:50
# include<stdio.h> # include<string.h> # include<cmath> # define N 60 # define V N*N int L[V],R[V];//记录左右方向的双向链表 int U[V],D[V];//记录上下方向的双向链表 int C[V];//指向其列指针头的地址 int H[N];//行指针头 int S[N];//记录列链表中节点的总数 int size,n,m,ak; int mark[N][N],visit[N];  const double eps=1e-7;  void prepare(int c)  {          for(int i=0;i<=c;i++)            {              S[i]=0;U[i]=D[i]=i;              L[i+1]=i;R[i]=i+1;            }            R[c]=0;            size=c+1;            memset(H,-1,sizeof(H));  }  void Link(int r,int c) {     S[c]++;C[size]=c;     U[size]=U[c];D[U[c]]=size;     D[size]=c;U[c]=size;     if(H[r]==-1) H[r]=L[size]=R[size]=size;     else     {         L[size]=L[H[r]];R[L[H[r]]]=size;         R[size]=H[r];L[H[r]]=size;     }     size++; } void remove(int Size) {     int j;     for(j=D[Size];j!=Size;j=D[j])         L[R[j]]=L[j],R[L[j]]=R[j]; } void resume(int Size) {     int j;     for(j=D[Size];j!=Size;j=D[j])         L[R[j]]=R[L[j]]=j; } int h() {     int count=0,i,j,k;     memset(visit,0,sizeof(visit));     for(i=R[0];i;i=R[i])     {         if(visit[i]) continue;         count++;         for(j=D[i];j!=i;j=D[j])         {             for(k=R[j];k!=j;k=R[k])                 visit[C[k]]=1;         }     }     return count; } void Dance(int k) {     int i,j,min,c;     if(k+h()>=ak) return;     if(!R[0])     {         if(k<ak) ak=k;         return;     }     for(min=N,i=R[0];i;i=R[i])         if(min>S[i]) min=S[i],c=i;     for(i=D[c];i!=c;i=D[i])     {         remove(i);         for(j=R[i];j!=i;j=R[j])             remove(j);         Dance(k+1);         for(j=R[i];j!=i;j=R[j])             resume(j);         resume(i);     } }struct point  {      double x,y;  }rar[55],city[55];  double dis(point a,point b)  {      return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));  }  int main()  {       int ca,k,K;       scanf("%d",&ca);       while(ca--)       {        scanf("%d%d%d",&n,&m,&K);        for(int i=1;i<=n;i++)        scanf("%lf%lf",&city[i].x,&city[i].y);      for(int i=1;i<=m;i++)      scanf("%lf%lf",&rar[i].x,&rar[i].y);                 double L=0,R=10000,mid;               while(R-L>eps)        {           prepare(n);          mid=(R+L)/2.0;          for(int i=1;i<=m;i++)          {              for(int j=1;j<=n;j++)              {                  if(dis(rar[i],city[j])<mid+eps)                  Link(i,j);              }          }          ak=N+1;          Dance(0);          //printf("%d###\n",ak);          if(ak>K)          {              L=mid;          }          else           {              R=mid;          }        }        printf("%.6lf\n",R);        }   return 0;  }