hdu 5046二分+DXテンプレート

29752 ワード

http://acm.hdu.edu.cn/showproblem.php?pid=5046
n都市がk空港を建設することによって、各都市の一番近い空港の距離の最大値が最小になる。
二分+DX
テンプレートの問題
#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; }