Description

给定一张 \(n \times m\) 的网格图,每个格子可以取值为 \(1,2,0\)。要求将一些边线染黑,使得所有的 \(1,2\) 被割开。\(n,m \le 100\)

Solution

最小割,每个点向四周的点连边(1),\(S \to 1, 2 \to T (\infty)\),对于 \(0\) 点,只需要将其作为中间点,而不需要考虑其归属。

#include <bits/stdc++.h>
using namespace std;
const int N = 55555, MAXN = 262144;
#define reset(x) memset(x, 0, sizeof x)
struct Graph
{
    int n, m, M, S, T, head[N], cur[N], dep[N], gap[N], q[N];
    long long ans;
    struct ed
    {
        int to, nxt, val;
    } edge[MAXN];
    void init(int n0, int m0, int S0, int T0)
    {
        n = n0, m = m0, S = S0, T = T0, M = 1, reset(gap);
        reset(head), reset(cur), reset(dep), reset(q);
    }
    void _make(int u, int v, int w)
    {
        edge[++M] = (ed){v, head[u], w}, head[u] = M;
    }
    void make(int u, int v, int w)
    {
        _make(u, v, w);
        _make(v, u, 0);
    }
    int dfs(int u, int mx)
    {
        if (u == T)
            return mx;
        int num = 0, f;
        for (int &i = cur[u], v; i; i = edge[i].nxt)
            if (dep[v = edge[i].to] == dep[u] - 1 && (f = edge[i].val))
                if (edge[i].val -= (f = dfs(v, min(mx - num, f))), edge[i ^ 1].val += f, (num += f) == mx)
                    return num;
        if (!--gap[dep[u]++])
            dep[S] = n + 1;
        return ++gap[dep[u]], cur[u] = head[u], num;
    }
    void solve()
    {
        for (int i = 1; i <= n; ++i)
            cur[i] = head[i];
        ans = 0;
        for (gap[0] = n; dep[S] <= n; ans += dfs(S, 0x7fffffff))
            ;
    }
} g;

const int di[4] = {0, 0, 1, -1};
const int dj[4] = {1, -1, 0, 0};

signed main()
{
    int n, m;
    cin >> n >> m;

    function<bool(int, int)> check = [&](int i, int j) -> bool {
        return i >= 1 && j >= 1 && i <= n && j <= m;
    };

    function<int()> id_source = [&]() -> int {
        return 1;
    };

    function<int()> id_target = [&]() -> int {
        return 2;
    };

    function<int(int, int)> id_grid = [&](int i, int j) -> int {
        return 2 + (i - 1) * m + j;
    };

    g.init(4*n*m, 0, id_source(), id_target());

    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            int t;
            cin >> t;
            if (t == 1)
            {
                g.make(id_source(), id_grid(i, j), 99999);
            }
            else if (t == 2)
            {
                g.make(id_grid(i, j), id_target(), 99999);
            }

            for (int k = 0; k < 4; k++)
            {
                int ni = i + di[k];
                int nj = j + dj[k];

                if (check(ni, nj))
                {
                    g.make(id_grid(i, j), id_grid(ni, nj), 1);
                }
            }
        }
    }

    g.solve();

    cout << g.ans << endl;
}

相关文章:

  • 2021-06-14
  • 2022-01-14
  • 2021-11-12
  • 2021-12-15
  • 2021-05-22
  • 2021-08-20
猜你喜欢
  • 2021-09-11
  • 2021-11-12
  • 2021-06-10
  • 2022-12-23
  • 2022-03-08
  • 2021-11-18
  • 2021-10-10
相关资源
相似解决方案