DLX重复覆盖 hdu5046 Airport

来源:互联网 发布:linux 查看cpu日志 编辑:程序博客网 时间:2024/05/21 10:59

传送门:点击打开链接

题意:有N个城市,现在要修K个机场,使N个城市到最近机场的最大距离最小,问K个机场应该修在哪里,机场必须修在城市中。

思路:二分N个城市到最近机场的最大距离,于是可以转换成,知道每个点,知道它的半径,能覆盖到这些点,问是否能选K个点,使得所在范围覆盖所有的点。那么这部分可以用DLX重复覆盖来做

wa点:二分的时候,l,m,r都要使用LL才行,因为可能会爆int

#include<map>#include<set>#include<cmath>#include<stack>#include<queue>#include<cstdio>#include<cctype>#include<string>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#include<functional>#define fuck printf("fuck")#define FIN freopen("input.txt","r",stdin)#define FOUT freopen("output.txt","w+",stdout)using namespace std;typedef long long LL;const int MX = 60 + 5;const int MN = 3600 + 5;const int INF = 0x3f3f3f3f;struct DLX {    int m, n, ans;    int H[MX], S[MX], vis[MX];    int Row[MN], Col[MN], rear;    int L[MN], R[MN], U[MN], D[MN];    void Init(int _m, int _n) {        m = _m; n = _n;        rear = n; ans = INF;        for(int i = 0; i <= n; i++) {            S[i] = 0;            L[i] = i - 1;            R[i] = i + 1;            U[i] = D[i] = i;        }        L[0] = n; R[n] = 0;        for(int i = 1; i <= m; i++) {            H[i] = -1;        }    }    void Link(int r, int c) {        int rt = ++rear;        Row[rt] = r; Col[rt] = c; S[c]++;        D[rt] = D[c]; U[D[c]] = rt;        U[rt] = c; D[c] = rt;        if(H[r] == -1) {            H[r] = L[rt] = R[rt] = rt;        } else {            int id = H[r];            R[rt] = R[id]; L[R[id]] = rt;            L[rt] = id; R[id] = rt;        }    }    void Remove(int c) {        for(int i = D[c]; i != c; i = D[i]) {            R[L[i]] = R[i]; L[R[i]] = L[i];        }    }    void Resume(int c) {        for(int i = U[c]; i != c; i = U[i]) {            R[L[i]] = L[R[i]] = i;        }    }    int h() {        int ret = 0;        memset(vis, 0, sizeof(vis));        for(int c = R[0]; c != 0; c = R[c]) {            if(!vis[c]) {                ret++;                vis[c] = 1;                for(int i = D[c]; i != c; i = D[i]) {                    for(int j = R[i]; j != i; j = R[j]) {                        vis[Col[j]] = 1;                    }                }            }        }        return ret;    }    bool Dance(int cnt, int K) {        if(cnt + h() > K) return false;        if(R[0] == 0) return true;        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(cnt + 1, K)) return true;            for(int j = L[i]; j != i; j = L[j]) Resume(j);            Resume(i);        }        return false;    }} G;LL X[MX], Y[MX], W[MX][MX];LL dist(int i, int j) {    return abs(X[i] - X[j]) + abs(Y[i] - Y[j]);}int main() {    int T, n, K, ansk = 0; //FIN;    scanf("%d", &T);    while(T--) {        scanf("%d%d", &n, &K);        for(int i = 1; i <= n; i++) {            scanf("%I64d%I64d", &X[i], &Y[i]);        }        for(int i = 1; i <= n; i++) {            for(int j = 1; j <= n; j++) {                W[i][j] = dist(i, j);            }        }        LL L = 0, R = 4e9, m, ans;        while(L <= R) {            m = (L + R) >> 1;            G.Init(n, n);            for(int i = 1; i <= n; i++) {                for(int j = 1; j <= n; j++) {                    if(W[i][j] <= m) G.Link(i, j);                }            }            if(G.Dance(0, K)) {                ans = m;                R = m - 1;            } else L = m + 1;        }        printf("Case #%d: %I64d\n", ++ansk, ans);    }    return 0;}

0 0
原创粉丝点击