BZOJ 3630: [JLOI2014]镜面通道 (网络流 +计算几何)

水能流过的地方光都能达到

呵呵.jpg

那就是裸的最小割(割开上边界和下边界)了…

判矩形和圆相交的时候就用圆心对矩形求一次点到矩形的最近距离(类似KD树的预估函数).

CODE

#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
template<typename T>inline void read(T &num) {
    char ch; int flg=1;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')flg=-flg;
    for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
    num*=flg;
}
const int MAXN = 605;
const int MAXM = 1000005;
const int inf = 1e9;
struct edge { int to, nxt, c, w, C; }e[MAXM];
int n, m, S, T, cnt, fir[MAXN], info[MAXN];
inline void add(int u, int v, int cc) {
    e[cnt] = (edge){ v, fir[u], cc }, fir[u] = cnt++;
    e[cnt] = (edge){ u, fir[v], 0 }, fir[v] = cnt++;
}
namespace SAP {
    int h[MAXN], gap[MAXN], sz;
    int aug(int u, int Max) {
        if(u == T) return Max;
        int flow = 0, delta, v;
        for(int i = info[u]; ~i; i = e[i].nxt)
            if(e[i].c && h[v=e[i].to]+1 == h[u]) {
                delta = aug(v, min(Max-flow, e[i].c));
                e[i].c -= delta, e[i^1].c += delta; info[u] = i;
                if((flow+=delta) == Max || h[S] == sz) return flow;
            }
        if(!(--gap[h[u]])) h[S] = sz;
        ++gap[++h[u]]; info[u] = fir[u];
        return flow;
    }
    inline int sap() {
        memcpy(info, fir, sizeof fir);
        int flow = 0; sz = T;
        while(h[S] < sz)
            flow += aug(S, inf);
        return flow;
    }
}
int X, Y, a[305], b[305], c[305], d[305], tp[305];
inline bool up(int i) {
    if(tp[i] == 1) return b[i]+c[i] >= Y && b[i]-c[i] <= Y;
    return d[i] >= Y && b[i] <= Y;
}
inline bool down(int i) {
    if(tp[i] == 1) return b[i]+c[i] >= 0 && b[i]-c[i] <= 0;
    return d[i] >= 0 && b[i] <= 0;
}
inline long long sqr(int x) { return 1ll * x * x; }
inline bool meet(int i, int j) {
    if(tp[i] == tp[j]) {
        if(tp[i] == 1) return sqr(a[i]-a[j]) + sqr(b[i]-b[j]) <= sqr(c[i]+c[j]);
        return !(a[i] > b[j] || a[j] > b[i] || c[i] > d[j] || c[j] > d[i]);
    }
    if(tp[i] == 2) swap(i, j);
    return sqr(max(a[i]-c[j], 0) + max(a[j]-a[i], 0)) + sqr(max(b[i]-d[j], 0) + max(b[j]-b[i], 0)) <= sqr(c[i]);
}
int main () {
    memset(fir, -1, sizeof fir);
    read(X), read(Y), read(n);
    for(int i = 1; i <= n; ++i) {
        read(tp[i]), read(a[i]), read(b[i]), read(c[i]);
        if(tp[i] == 2) read(d[i]);
    }
    S = 0, T = 2*n+1;
    for(int i = 1; i <= n; ++i) add(i, i+n, 1);
    for(int i = 1; i <= n; ++i) if(up(i)) add(S, i, inf);
    for(int i = 1; i <= n; ++i) if(down(i)) add(i+n, T, inf);
    for(int i = 1; i <= n; ++i)
        for(int j = i+1; j <= n; ++j)
            if(i != j && meet(i, j)) add(i+n, j, inf), add(j+n, i, inf);
    printf("%d
", SAP::sap());
}
原文地址:https://www.cnblogs.com/Orz-IE/p/12039298.html