BZOJ1822 [JSOI2010] Frozen Nova frozen half-wave maximum flow +

Topic Portal

https://lydsy.com/JudgeOnline/problem.php?id=1822

answer

For a long time did not do network flow, network flow did not expect ...

First, determine what a violent attack between Lich and whether a wizard. Enumeration tree in general is seeking to look at the center of the Lich elves and even line distance, radius and compare it.

Then Lich side to be able to attack the elves built. Dichotomy then answer \ (MID \) , S $ $ from each sprite to build a capacity \ (\ lfloor \ frac {mid } t \ rfloor + 1 \) edges, each sprite to \ (T \) Construction a \ (1 \) side. The maximum flow run on it.


Here is the code. Because this is a bipartite graph, so is the complexity of a Dinic \ (O (m \ n-sqrt) = O (n-^ {\} 52 is FRAC) \) . Therefore, the total time complexity is \ (O (\ OperatorName Dinic} {(n-, ^ n-2) \ log ANS) \) .

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back

template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}

typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;

template<typename I>
inline void read(I &x) {
    int f = 0, c;
    while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    x = c & 15;
    while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    f ? x = -x : 0;
}

const int NN = 200 + 7;
const int N = 200 * 2 + 2 + 7;
const int M = 200 * 200 + 200 * 2 + 7;
const int INF = 0x3f3f3f3f;
const double eps = 1e-10;

int n, m, k, nod, allsize, S, T, tot1, mxt, hd, tl;
int ar[NN], at[NN], cr[NN];
int dis[N], cur[N], q[N];

struct Point {
    int x, y;
    inline Point() {}
    inline Point(const int &x, const int &y) : x(x), y(y) {}
} a[NN], b[NN], c[NN];
inline Point operator - (const Point &a, const Point &b) { return Point(a.x - b.x, a.y - b.y);}
inline int dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }
inline int cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x;}
//inline double dist(const Point &a, const Point &b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }
inline int dist2(const Point &a, const Point &b) { return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y); }

struct Edge { int to, ne, f; } g[M << 1]; int head[N], tot = 1;
inline void addedge(int x, int y, int z) { g[++tot].to = y, g[tot].f = z, g[tot].ne = head[x], head[x] = tot;}
inline void adde(int x, int y, int z) { addedge(x, y, z), addedge(y, x, 0); }

inline bool bfs() {
    memset(dis, 0x3f, allsize), memcpy(cur, head, allsize);
    q[hd = 0, tl = 1] = S, dis[S] = 0;
    while (hd < tl) {
        int x = q[++hd];
        for fec(i, x, y) if (g[i].f && dis[y] == INF) {
            dis[y] = dis[x] + 1, q[++tl] = y;
            if (y == T) return 1;
        }
    }
    return 0;
}
inline int dfs(int x, int a) {
    if (x == T || !a) return a;
    int flow = 0, f;
    for (int &i = cur[x]; i; i = g[i].ne) {
        int y = g[i].to;
        if (dis[y] != dis[x] + 1 || !(f = dfs(y, std::min(a, g[i].f)))) continue;
        g[i].f -= f, g[i ^ 1].f += f;
        flow += f, a -= f;
        if (!a) break;
    }
    if (!flow) dis[x] = INF;
    return flow;
}
inline int dinic() {
    int ans = 0;
    while (bfs()) ans += dfs(S, INF);
    return ans;
}

inline void build() {
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) if (dist2(a[i], b[j]) <= ar[i] * ar[i]) {
            bool flag = 1;
            for (int kk = 1; kk <= k; ++kk) {
                int s = abs(cross(b[j] - a[i], c[kk] - a[i]));
                if ((ll)dot(c[kk] - b[j], a[i] - b[j]) * dot(c[kk] - a[i], b[j] - a[i]) > 0 && (ll)s * s <= (ll)cr[kk] * cr[kk] * dist2(b[j], a[i])) { flag = 0; break; }
                if (dist2(c[kk], b[j]) <= cr[kk] * cr[kk] || dist2(c[kk], a[i]) <= cr[kk] * cr[kk]) { flag = 0; break; }
            }
            if (flag) adde(i, j + n, 1);
        }
    S = n + m + 1, nod = T = S + 1, allsize = (nod + 1) * sizeof(int);
    for (int i = 1; i <= m; ++i) adde(i + n, T, 1);
    tot1 = tot;
    for (int i = 1; i <= n; ++i) adde(S, i, 0);
}

inline bool check(const int &mid) {
    for (int i = 2; i <= tot1; i += 2) g[i].f = 1, g[i ^ 1].f = 0;
    for (int i = 1, j = tot1 + 1; i <= n; ++i, j += 2) g[j].f = mid / at[i] + 1, g[j ^ 1].f = 0;
    return dinic() >= m;
}

inline void work() {
    build();
    int l = 0, r = mxt * m;
    while (l < r) {
        int mid = (l + r) >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    if (!check(l)) puts("-1");
    else printf("%d\n", l);
}

inline void init() {
    read(n), read(m), read(k);
    for (int i = 1; i <= n; ++i) read(a[i].x), read(a[i].y), read(ar[i]), read(at[i]), smax(mxt, at[i]);
    for (int i = 1; i <= m; ++i) read(b[i].x), read(b[i].y);
    for (int i = 1; i <= k; ++i) read(c[i].x), read(c[i].y), read(cr[i]);
}

int main() {
#ifdef hzhkk
    freopen("hkk.in", "r", stdin);
#endif
    init();
    work();
    fclose(stdin), fclose(stdout);
    return 0;
}

Guess you like

Origin www.cnblogs.com/hankeke/p/BZOJ1822.html