hdu 5046 二分+DLX模板

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;
 }