hdu5046 从n个村庄选k个机场使->所有村庄到他最近的机场的最大距离最小 :二分距离/DLX可重复覆盖

这是去年上海赛区网络赛的题目,当时过了好多队我们赛后才知道是DLX,太low了

现在回来做竟是一道裸的二分距离+DLX重复覆盖(忽然想起来是kuangbin巨巨出的题2333

  1 #include<stdio.h>
  2 #include<math.h>
  3 #include<string.h>
  4 #include<algorithm>
  5 #define eps 1e-8
  6 #define LL long long
  7 using namespace std;
  8 struct dian{
  9   int x,y;
 10 }a[65];
 11 int k;
 12 LL dis(dian n1,dian n2)
 13 {
 14   return abs((LL)n1.x-(LL)n2.x)+abs((LL)n1.y-(LL)n2.y);
 15 }
 16 struct DLX{
 17   int n,m,size,ansd,ans[65];
 18   int U[4005],D[4005],L[4005],R[4005];
 19   int Row[4005],Col[4005],H[65],S[65];
 20   void init(int _n,int _m){
 21     n=_n; m=_m;
 22     for (int i=0;i<=m;i++){
 23       S[i]=0;
 24       U[i]=D[i]=i;
 25       L[i]=i-1; R[i]=i+1;
 26     }
 27     R[m]=0; L[0]=m;
 28     size=m;
 29     for (int i=1;i<=n;i++) H[i]=-1;
 30   }
 31   void link(int r,int c){
 32     S[c]++;
 33     Col[++size]=c; Row[size]=r;
 34     D[size]=D[c]; U[D[c]]=size;
 35     U[size]=c; D[c]=size;
 36     if (H[r]<0) H[r]=L[size]=R[size]=size;
 37     else{
 38       R[size]=R[H[r]];
 39       L[R[H[r]]]=size;
 40       L[size]=H[r];
 41       R[H[r]]=size;
 42     }
 43   }
 44   void remove(int c){
 45     for (int i=D[c];i!=c;i=D[i])
 46       L[R[i]]=L[i],R[L[i]]=R[i];
 47   }
 48   void resume(int c){
 49     for (int i=U[c];i!=c;i=U[i])
 50       L[R[i]]=R[L[i]]=i;
 51   }
 52   int v[3005];
 53   int f(){
 54     int tmp=0;
 55     for (int c=R[0];c!=0;c=R[c]) v[c]=1;
 56     for (int c=R[0];c!=0;c=R[c])
 57       if (v[c]){
 58         tmp++; v[c]=0;
 59         for (int i=D[c];i!=c;i=D[i])
 60           for (int j=R[i];j!=i;j=R[j])
 61             v[Col[j]]=0;
 62       }
 63     return tmp;
 64   }
 65   int Dance(int d){
 66     if (d+f()>k) return 0;
 67     if (R[0]==0) return d<=k;
 68     int c=R[0];
 69     for (int i=R[0];i;i=R[i])
 70       if (S[i]<S[c]) c=i;
 71     for (int i=D[c];i!=c;i=D[i]){
 72       remove(i);
 73       for (int j=R[i];j!=i;j=R[j]) remove(j);
 74       if (Dance(d+1)) return 1;
 75       for (int j=L[i];j!=i;j=L[j]) resume(j);
 76       resume(i);
 77     }
 78     return 0;
 79   }
 80 }G;
 81 int main()
 82 {
 83   int T,t,n,m,i,j;
 84   LL l,r,mid;
 85   scanf("%d",&T);
 86   for (t=1;t<=T;t++){
 87     scanf("%d%d",&n,&k);
 88     for (i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
 89     l=0; r=4*1e9;
 90     while (l<r){
 91       mid=l+(r-l)/2;
 92       G.init(n,n);
 93       for (i=1;i<=n;i++)
 94         for (j=1;j<=n;j++)
 95           if (dis(a[i],a[j])<=mid) G.link(i,j);
 96       if (G.Dance(0)) r=mid;
 97       else l=mid+1;
 98     }
 99     printf("Case #%d: %I64d\n",t,l);
100   }
101   return 0;
102 }
View Code

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5046

posted on 2015-04-22 21:13  xiao_xin  阅读(204)  评论(2编辑  收藏  举报

导航