HDU 5046 Airport DLX

来源:互联网 发布:qq刷钻软件下载 编辑:程序博客网 时间:2024/06/05 12:02

【题目大意】

有n个城市,你可以从中选k个城市建立飞机场。建好飞机场后,城市i(1<=i<=n)距离最近的飞机场有一个距离值di。你的任务是选择一个建造方式,使得max(di)最小,输出这个最小值。

【思路】

基本是hdu 3656的原题,和hdu 4398也很像。

我们可以二分最小的距离值。如果城市i建立飞机场,存在城市j,满足两城市的距离<=二分的值。令mat[i][j] = 1,否则mat[i][j] = 0。这个表,就是精确覆盖的表,只不过这里允许重复覆盖。。。非精确覆盖问题,直接贴模板。。。

//#pragma comment(linker, "/STACK:102400000,102400000")#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<cmath>#include<cctype>#include<string>#include<algorithm>#include<iostream>#include<ctime>#include<map>#include<set>using namespace std;#define MP(x,y) make_pair((x),(y))#define PB(x) push_back(x)typedef __int64 LL;//typedef unsigned __int64 ULL;/* ****************** */const int INF=100011122;const double INFF=1e100;const double eps=1e-8;//const LL mod=1000000007;const int NN=100010;const int MM=2000010;/* ****************** */const int maxn=61;const int maxr=61;const int maxnode=3700;int sz,ansd;int S[maxn],H[maxr];int row[maxnode],col[maxnode];int L[maxnode],D[maxnode],U[maxnode],R[maxnode];bool mat[61][61];bool vis[61];LL dis[61][61];LL x[61], y[61];LL tf[4000];int kk;void dl_init(int n){    memset(H,-1,sizeof(H));    int i;    for(i=0;i<=n;i++)    {        U[i]=D[i]=i;        L[i]=i-1;        R[i]=i+1;        S[i]=0;    }    L[0]=n;    R[n]=0;    sz=n+1;}void dl_add(int r,int c){    row[sz]=r,col[sz]=c;    S[c]++;    U[sz]=U[c];    D[sz]=c;    D[ U[c] ]=sz;    U[c]=sz;    if(H[r]==-1)    {        H[r]=L[sz]=R[sz]=sz;    }    else    {        L[sz]=L[H[r]];        R[sz]=H[r];        R[ L[sz] ]=sz;        L[ H[r] ]=sz;    }    sz++;}void remove(int id){    int i;    for(i=D[id];i!=id;i=D[i])    {        L[R[i]]=L[i];        R[L[i]]=R[i];    }}void restore(int id){    int i;    for(i=U[id];i!=id;i=U[i])    {        R[L[i]]=i;        L[R[i]]=i;    }}int h(){    int i,j,k,ans=0;    memset(vis,false,sizeof(vis));    for(i=R[0];i!=0;i=R[i])    {        if(!vis[i])        {            ans++;            vis[i]=true;            for(j=D[i];j!=i;j=D[j])                for(k=R[j];k!=j;k=R[k])                    vis[ col[k] ]=true;        }    }    return ans;}void dl_dfs(int d){    if(ansd <= kk)        return;    if(d+h() > kk)        return;    if(R[0]==0)    {        ansd=d;        return;    }    int i,j,c=R[0];    for(i=R[0];i!=0;i=R[i])        if(S[i]<S[c])            c=i;    for(i=D[c];i!=c;i=D[i])    {        remove(i);        for(j=R[i];j!=i;j=R[j])            remove(j);        dl_dfs(d+1);        for(j=L[i];j!=i;j=L[j])            restore(j);        restore(i);    }}int goo(int n,LL dd){    int i,j;    for(i = 1; i <= n; i ++)    {        for(j = 1; j <= n; j++)        {            if(dis[i][j] <= dd)                mat[i][j] = true;            else                mat[i][j] = false;        }    }    dl_init(n);    for(i=1;i<=n;i++)    {        for(j=1;j<=n;j++)        {            if(mat[i][j] || i==j)            {                dl_add(i,j);            }        }    }    ansd=n;    dl_dfs(0);    return ansd;}LL f_abs(LL x){    if(x >= 0)return x;    return -x;}int main(){    int cas, ee = 0;    int n, k, i, j, tol, m;    int l ,r, mid;    scanf("%d", &cas);    while(cas--)    {        scanf("%d%d", &n, &k);        kk = k;        for(i = 1; i <= n; i ++)        {            scanf("%I64d%I64d",&x[i],&y[i]);        }        tol = 0;        for(i = 1; i <= n; i ++)            for(j = 1; j <= n; j ++)            {                dis[i][j] = f_abs(x[i]-x[j]) + f_abs(y[i]-y[j]);                tf[++tol] = dis[i][j];            }        sort(tf+1,tf+1+tol);        m = unique(tf+1,tf+1+tol) - tf - 1;        tf[0] = -1;        l = 0;        r = m;        while(l + 1 < r)        {            mid = (l + r)>>1;            if(goo(n, tf[mid]) <= k)                r = mid;            else                l = mid;        }        printf("Case #%d: ", ++ee);        printf("%I64d\n",tf[r]);    }    return 0;}


0 0