[Logu P2472] [SCOI2007] Lizard

Keywords: PHP network less REST

Title link:

Lizard

Title Analysis:

With a network stream, let's first analyze the problem:
In a \(r*c\) diagram, some numbers are distributed, and others are filled with \(0\). We start from the specified numbers and can move to a number within \(d\) or outside the diagram each time. The original number will be \(-1\) and can't be negative at any time.Each number walk affects each other.How many departures can reach outside the map?

List the limitations of this question:

  • Only one lizard can stand on each stone post
  • Each stone pillar passes through its height at most times
  • Between pillars, the distance between the pillar and the plot boundary is less than or equal to \(d\)

First, my angle starts with the limitations of each pillar itself.We know that a stone with a height of \(h\) can be passed up to \(h\) times (obviously, a lizard is not going back because this is a waste of resources), and one of the basic properties of network flow is that each edge has at most a full upper limit (equivalent to an upper limit), so consider using the height of the stone column as a networkLimitations on edges of network building.But each stone pillar is a point. What should we do? Consider breaking down each stone pillar, breaking the point numbered \(i\) into \(i\) and \(i + r * c\), then connecting all the edges that flow into this point to \(i), connecting all the edges that flow out of this point to \(i+r*c\), and adding a limit to the edge between the two points (flow rate is \(h\)).This is the treatment of stone pillars and I think it is the most critical step in this issue.

The rest is better.
For the limit of "only one lizard can stand on each stone pillar", use "only one lizard can stand" as the upper limit, and the source point is connected to each stone pillar where the lizard is located with a capacity of \(1\)
For stones and columns, the distance between the stones and the boundary of the graph is less than or equal to \(d\) to reach the limit, because the graph is small, we consider enumerating two points directly by violence. If both points have stones and the distance is less than or equal to \(d\), then we directly consider connecting an INF\ edge between two stones:There are no restrictions other than distance, which has already been determined and the restrictions for each stone pillar have been added during the process of dismantling, so there is no need for additional capacity restrictions, just connect \(INF\).For the restrictions on reaching the boundary, we also connect an \(INF\) edge (similar to the previous reason), and the distance judgment only needs to be made in terms of the transverse direction, since according to the Pythagorean Theorem, the transverse direction is obviously larger than \(d\) and the diagonal direction is also larger than \(d).

Code:

// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define INF (1000000000 + 7)
#define N (10005 + 5)
#define M (100000 + 5)
#define int long long
using namespace std;
inline int read(){
    int cnt = 0, f = 1; char c;
    c = getchar();
    while (!isdigit(c)) {
        if(c == '-') f = -f;
        c = getchar();
    }
    while (isdigit(c)) {
        cnt = cnt * 10 + c - '0';
        c = getchar();
    }   
    return cnt * f;
}
int r, c, d, tot = 1, n;
int S, T;
int first[M], nxt[M], to[M], flow[M];
int mapp[N][N], a[N][N];
int dep[M], cnt[M];
char lizard[N][N];
inline void Add(int x, int y, int z) {
    nxt[++tot] = first[x], first[x] = tot, to[tot] = y, flow[tot] = z;
    nxt[++tot] = first[y], first[y] = tot, to[tot] = x, flow[tot] = 0;
} 
inline bool pd(int i, int j) {
    if (i <= d || j <= d) return true;
    if (r - i + 1 <= d || c - j + 1 <= d) return true;
    return false;
}
inline void build() {
    S = 1;
    for (register int i = 1; i <= r; i++)
        for (register int j = 1; j <= c; j++)
            a[i][j] = ++tot;

    for (register int i = 1; i <= r; i++)
        scanf("%s", lizard[i] + 1);
    for (register int i = 1; i <= r; i++)
        for (register int j = 1; j <= c; j++)
            mapp[i][j] = lizard[i][j] - '0';
            
    T = r * c * 2 + 2, tot = 1;

    for (register int i = 1; i <= r; i++)
            scanf("%s", lizard[i] + 1); 
    
    for (register int i = 1; i <= r; i++)
        for (register int j = 1; j <= c; j++) 
            if (mapp[i][j]) {
                Add(a[i][j], a[i][j] + r * c, mapp[i][j]);
                if (pd(i, j)){
                     Add(a[i][j] + r * c, T, INF);
//                   cout<<i<<" "<<j<<endl;
                }
            }
            
    for (register int i = 1; i <= r; i++)
        for (register int j = 1; j <= c; j++) 
            for (register int k = 1; k <= r; k++) 
                for (register int p = 1; p <= c; p++) {
                    if (i == k && j == p) continue;
                    if (mapp[i][j] && mapp[k][p])
                    if ((i - k) * (i - k) + (j - p) * (j - p) <= d * d)
                        Add(a[i][j] + r * c, a[k][p], INF);
//                      Add(a[k][p] + r * c, a[i][j], INF);
                    }
    for (register int i = 1; i <= r; i++)
        for (register int j = 1; j <= c; j++)
            if (lizard[i][j] == 'L') Add(S, a[i][j], 1), ++n;
}
inline void bfs_(int s) {
    memset(dep, 0xff, sizeof(dep));
    dep[s] = 0;
    cnt[0] = 1;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
        int p = q.front();
        q.pop();
        for (register int i = first[p]; i >= 2; i = nxt[i]) {
            int v = to[i];
            if (dep[v] == -1) {
                ++cnt[dep[v] = dep[p] + 1];
                q.push(v);
            }
        }
    }
}

int max_flow;

int dfs_(int p, int f) {
    if (p == T) {
        max_flow += f;
        return f;
    }
    int u = 0;
    for (register int i = first[p]; i >= 2; i = nxt[i]) {
        int v = to[i];
        if (flow[i] && dep[v] == dep[p] - 1) {
            int uu = dfs_(v, min(flow[i], f - u)); 
            if (uu) {
                flow[i] -= uu;
                flow[i ^ 1] += uu;
                u += uu;
            }
            if (u >= f) {
                return u;
            }
        }
    }
    if (!--cnt[dep[p]]) {
        dep[S] = r * c * 2 + 10;
    }
    ++cnt[++dep[p]];
    return u;
}
signed main() {
    r = read(); c = read(); d = read();
    build();
    bfs_(T);
    while (dep[S] < 2 * r * c + 9) dfs_(S, INF);
    printf("%lld", n - max_flow);
    return 0;
}

Posted by Nicholas Reed on Fri, 19 Jul 2019 10:42:01 -0700