码迷,mamicode.com
首页 > 其他好文 > 详细

hdu5064 DLX可重复覆盖+二分

时间:2015-07-31 21:39:48      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:

这题题意是 给了n个城市 在其中小于等于k个城市建立机场然后 使得最远的那个离机场的城市距离最短

二分答案 ,我们对于每次的mid 重新建图然后再来一次DLX,每个点可以覆盖的点建立一条联系就ok了

技术分享
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
#include <vector>
using namespace std;
const int maxn=61;
const int maxnode=61*61;
int K;
struct DLX
{
     int numCol,numRow,U[maxnode],D[maxnode],L[maxnode],R[maxnode],row[maxnode],col[maxnode];
     int S[maxn],H[maxn],siz;
     void init(int n,int m)
     {
         this->numCol=n; this->numRow=m;
         for(int i=0; i<=numCol; i++)
            {
                S[i]=0;
                U[i]=D[i]=i;
                L[i]=i-1; R[i]=i+1;
            }
          L[0]=n; R[n]=0;
          for(int i=0; i<=numRow; i++)H[i]=-1;
         siz=n+1;
     }
     void link(int r, int c)
     {
         S[c]++;
         row[siz]=r;
         col[siz]=c;
         U[siz]=U[c];
         D[siz]=c;
         D[U[siz]]=siz;
         U[D[siz]]=siz;
         if(H[r]==-1){
            H[r]=L[siz]=R[siz]=siz;
         }else {
            L[siz]=H[r];
            R[siz]=R[H[r]];
            R[L[siz]]=siz;
            L[R[siz]]=siz;
            H[r]=siz;
         }
         siz++;
     }
     bool v[maxnode];
     int AX()
     {
         for(int c=R[0]; c!=0; c=R[c])v[c]=true;
         int ret=0;
         for(int c=R[0]; c!=0; c=R[c])
            if(v[c])
            {
                ret++;
                v[c]=false;
                for(int i=D[c];i!=c; i=D[i])
                    for(int j=R[i]; j!=i; j=R[j])
                       v[col[j]]=false;
            }
        return ret;
     }
     void remove(int c)
     {
          for(int i=D[c]; i!=c ; i=D[i])
            L[R[i]]=L[i],R[L[i]]=R[i];
     }
     void resume(int c)
     {
         for(int i=U[c]; i!=c; i=U[i])
            L[R[i]]=R[L[i]]=i;
     }
     bool Dance(int d)
     {
         if(AX()+d>K)return false;
         if(R[0]==0)return d<=K;
         int c=R[0];
         for(int i=R[0]; i!=0; i=R[i])
            if(S[i]<S[c])c=i;
         for(int i=D[c];i!=c; i=D[i] )
            {
                remove( i );
                for(int j=R[ i ]; j!=i; j=R[ j ])remove( j );
                if(Dance(d+1))return true;
                for(int j=L[ i ]; j!=i; j=L[ j ])resume( j );
                resume( i );
            }
            return false;
     }

}g;
struct point
{
    int x,y;
    void input()
    {
        scanf("%d%d",&x,&y);
    }
}city[maxn];
long long dis(point a, point b)
{
    return (long long)abs(a.x-b.x)+(long long)abs(a.y-b.y);
}
int main()
{
    int cas;
    scanf("%d",&cas);
    for(int cc=1; cc<=cas; cc++)
        {
            int n;
            scanf("%d%d",&n,&K);
            for(int i=0; i<n; i++)
                city[i].input();
            long long L=0,R=100000000000LL;
            long long ans=0;
            while(L<=R)
                {
                    long long mid=(L+R)>>1;
                    g.init(n,n);
                    for(int i=0;i<n;i++)
                        for(int j=0; j<n;j++)
                        if(dis(city[i],city[j])<=mid)
                        g.link(i+1,j+1);
                    if(g.Dance(0)){R=mid-1;ans=mid; }
                    else L=mid+1;
                }
                printf("Case #%d: %I64d\n",cc,ans);
        }
    return 0;
}
View Code

 

hdu5064 DLX可重复覆盖+二分

标签:

原文地址:http://www.cnblogs.com/Opaser/p/4693184.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!