• [ZJOI2009] 狼和羊的故事


    Description

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

    Solution

    最小割,每个点向四周的点连边(1),(S o 1, 2 o 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;
    }
    
    
  • 相关阅读:
    Java:day11
    Java:day10
    Java:day9
    Java:day8
    纯虚函数和抽象类
    C++的虚拟继承
    派生类构造函数、析构函数的定义和调用次序
    c++的继承方式——公有、保护、私有
    操作系统中系统调用的执行过程
    C++的类
  • 原文地址:https://www.cnblogs.com/mollnn/p/14091193.html
Copyright © 2020-2023  润新知