• 网络流24题 方格取数问题


    题目传送门

    好久没做网络流了……


    对棋盘进行黑白染色,黑色点连源点,白色点连汇点
    因为相邻的点不能同时选,所以要在相邻的点间连容量为(inf)的边
    然后用所有方格的价值和减去最小割即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #define INF 21474836
    using namespace std;
    int read() {
        int k = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') {
            k = k * 10 + c - 48, c = getchar();
        }
        return k * f;
    }
    struct zzz {
        int t, len, nex;
    }e[100010 << 1]; int head[10010], tot = 1;
    void add(int x, int y, int z) {
        e[++tot].t = y;
        e[tot].len = z;
        e[tot].nex = head[x];
        head[x] = tot;
    
        e[++tot].t = x;
        e[tot].len = 0;
        e[tot].nex = head[y];
        head[y] = tot;
    }
    int s = 1, t = 2, vis[10010];
    bool bfs() {
        queue <int> q; q.push(s);
        memset(vis, 0, sizeof(vis)); vis[s] = 1;
        while(!q.empty()) {
            int k = q.front(); q.pop();
            for(int i = head[k]; i; i = e[i].nex) {
                if(!vis[e[i].t] && e[i].len) {
                    vis[e[i].t] = vis[k] + 1; q.push(e[i].t);
                    if(e[i].t == t) return 1;
                }
            }
        }
        return vis[t];
    }
    int dfs(int flow, int pos) {
        if(!flow || pos == t) return flow;
        int fl, rest = 0;
        for(int i = head[pos]; i; i = e[i].nex) {
            if(vis[e[i].t] == vis[pos] + 1 && (fl = dfs(min(e[i].len, flow-rest), e[i].t))) {
                e[i].len -= fl, e[i^1].len += fl, rest += fl;
                if(rest == flow) return rest;
            }
        }
        if(rest < flow) vis[pos] = 0;
        return rest;
    
    }
    int dinic() {
        int ans = 0;
        while(bfs()) {
            ans += dfs(1 << 30, s);
            //cout << ans << endl;
        }
        return ans;
    }
    int map[110][110], n, m, sum;
    int fx[5] = {0, 1, -1, 0, 0},
        fy[5] = {0, 0, 0, 1, -1};
    inline int id(int x, int y) {
        return (x - 1) * m + y + 2;
    }
    int main() {
       n = read(), m = read();
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j)
                map[i][j] = read(), sum += map[i][j];
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j) {
                if((i+j) & 1) add(s, id(i, j), map[i][j]);
                else add(id(i, j), t, map[i][j]);
            }
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j) {
                if((i+j) & 1) {
                    for(int k = 1; k <= 4; ++k) {
                        int xx = i + fx[k], yy = j + fy[k];
                        if(xx < 1 || xx > n || yy < 1 || yy > m) continue;
                        add(id(i,j), id(xx, yy), INF);
                    }
                }
            }
        cout << sum - dinic();
    
        return 0;
    }
    

    双倍经验:Luogu P4474 王者之剑

  • 相关阅读:
    [py]str list切片-去除字符串首尾空格-递归思想
    [py]python面向对象的str getattr特殊方法
    [py]python多态-动态语言的鸭子类型
    [py]py2自带Queue模块实现了3类队列
    【Unity技巧】制作一个简单的NPC
    java7 新特性 总结版
    【游戏周边】Unity,UDK,Unreal Engine4或者CryENGINE——我应该选择哪一个游戏引擎
    【Unity Shaders】Transparency —— 使用alpha通道创建透明效果
    记录最近的几个bug
    理解WebKit和Chromium: 调试Android系统上的Chromium
  • 原文地址:https://www.cnblogs.com/morslin/p/11855247.html
Copyright © 2020-2023  润新知