http://acm.hdu.edu.cn/showproblem.php?pid=5046
n城市建k机场使得,是每个城市最近机场的距离的最大值最小化
二分+DLX
模板题
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <queue> #include <vector> #include <iostream> #include <algorithm> using namespace std; #define RD(x) scanf("%d",&x) #define RD2(x,y) scanf("%d%d",&x,&y) #define clr0(x) memset(x,0,sizeof(x)) typedef long long LL; const int INF=1000000005; const int N=4444; int m; struct node { int L[N],R[N],D[N],U[N],e; int col[N]; int H[N],num[N]; int visit[N],KK; void init(int n) { KK=0; int i; for(i=0;i<=n;i++) { if(i==n) L[i]=0; else L[i]=i+1; if(i==0) R[i]=n; else R[i]=i-1; num[i]=0; H[i]=-1; D[i]=U[i]=i; } e=n+1; } void add(int r,int c) { U[e]=c; D[e]=D[c]; U[D[c]]=e; D[c]=e; if(H[r]<0) H[r]=L[e]=R[e]=e; else { L[e]=L[H[r]]; R[e]=H[r]; R[L[H[r]]]=e; L[H[r]]=e; } num[c]++; col[e]=c; e++; } void remove(int c) { int i; for(i=D[c];i!=c;i=D[i]) { R[L[i]]=R[i]; L[R[i]]=L[i]; } } void resume(int c) { int i; for(i=U[c];i!=c;i=U[i]) { L[R[i]]=R[L[i]]=i; } } int astar() { KK++; int ans=0,i,j,k; for(i=L[0];i!=0;i=L[i]) if(KK!=visit[i]) { visit[i]=KK; ans++; for(j=D[i];j!=i;j=D[j]) for(k=L[j];k!=j;k=L[k]) { visit[col[k]]=KK; } } return ans; } int DFS(int cnt) { if(L[0]==0) return 1; if(cnt+astar()>m) return 0; int tmp=INF,c,i; for(i=L[0];i!=0;i=L[i]) if(num[col[i]]<tmp) { tmp=num[col[i]]; c=i; } for(i=D[c];i!=c;i=D[i]) { remove(i); int j; for(j=L[i];j!=i;j=L[j]) remove(j); if(DFS(cnt+1)) return 1; for(j=R[i];j!=i;j=R[j]) resume(j); resume(i); } return 0; } }A; int n; LL s[65][65]; LL le[10005]; struct point{ LL x,y; }p[65]; int ok(LL M) { A.init(n); int i,j; for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(s[i][j]<=M) A.add(i,j); return A.DFS(0); } int main(){ int _,cas = 1; RD(_); while(_--){ RD2(n,m); for(int i = 1;i <= n;++i){ scanf("%I64d%I64d",&p[i].x,&p[i].y); } int mm = 0; for(int i = 1;i <= n;++i){ for(int j = 1;j <= n;++j){ LL len = abs(p[i].x - p[j].x) + abs(p[i].y - p[j].y); s[i][j] = s[j][i] = len; le[mm++] = len; } } sort(le,le+mm); mm = unique(le,le+mm)-le; int l = 0,r = mm - 1; LL ans = 0; while(l <= r){ LL mid = (l + r)>>1; if(ok(le[mid])) ans = le[mid],r = mid - 1; else l = mid + 1; } printf("Case #%d: ",cas++); cout<<ans<<endl; } return 0; }