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 }