zoukankan      html  css  js  c++  java
  • 网络流24题(09)方格取数问题(最大点权独立集 + 最小割最大流)

    题意:

    在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。

    思路:

    1. 不清楚何为“最小点权覆盖集”和“最大点权独立集”概念的请看这篇文章《最小割模型在信息学竞赛中的应用》;

    2. “最小点权覆盖集”和“最大点权独立集”是两个互补的概念,我们可以利用最小割求一个二分图的最小点权覆盖集;

    3. 把黑白相间染色,黑色部分为 X 集,白色部分为 Y 集,s 向 X 中的点引弧, Y 向 t 引弧,容量为 点权的大小;

       X 和 Y 中相邻的点由 X 向 Y 引弧,容量为无穷大,这么做的目的是为了让割边仅在 <s, X> 或 <Y, t> 中;

    4. 之所以这么做,是因为我们要求这个图中的“最大点权独立集”,依照其概念可以知道:任意两点不相邻<=>任意两点构成的边不在图中;

    5. 求上面网络的最大流,并且根据最小割最大流定理,再根据我们的建图,最大流->最小割->最小点权覆盖。输出 = 总点权 - 最大流;

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <vector>
    using namespace std;
    
    const int MAXN = 50*50;
    const int INFS = 0x7FFFFFFF;
    
    struct edge {
        int from, to, cap, flow;
        edge(int _from, int _to, int _cap, int _flow) 
            : from(_from), to(_to), cap(_cap), flow(_flow) {}
    };
    
    class Dinic {
    public:
        void initdata(int n, int s, int t) {
            this->n = n, this->s = s, this->t = t;
            edges.clear();
            for (int i = 0; i < n; i++)
                G[i].clear();
        }
        void addedge(int u, int v, int cap) {
            edges.push_back(edge(u, v, cap, 0));
            edges.push_back(edge(v, u, 0, 0));
            G[u].push_back(edges.size() - 2);
            G[v].push_back(edges.size() - 1);
        }
        bool BFS() {
            for (int i = 0; i < n; i++)
                vis[i] = false, d[i] = 0;
            queue<int> Q;
            Q.push(s);
            vis[s] = true;
            while (!Q.empty()) {
                int x = Q.front(); Q.pop();
                for (int i = 0; i < G[x].size(); i++) {
                    edge& e = edges[G[x][i]];
                    if (e.cap > e.flow && !vis[e.to]) {
                        vis[e.to] = true;
                        d[e.to] = d[x] + 1;
                        Q.push(e.to);
                    }
                }
            }
            return vis[t];
        }
        int DFS(int x, int aug) {
            if (x == t || aug == 0) return aug;
            int flow = 0;
            for (int i = 0; i < G[x].size(); i++) {
                edge& e = edges[G[x][i]];
                if (d[e.to] == d[x] + 1) {
                    int f = DFS(e.to, min(aug, e.cap - e.flow));
                    if (f <= 0) continue;
                    e.flow += f;
                    edges[G[x][i]^1].flow -= f;
                    flow += f;
                    aug -= f;
                    if (aug == 0) break;
                } 
            }
            return flow;
        }
        int maxflow() {
            int flow = 0;
            while (BFS()) {
                flow += DFS(s, INFS);
            }
            return flow;
        }
    private:
        vector<edge> edges;
        vector<int> G[MAXN];
        int n, s, t, d[MAXN];
        bool vis[MAXN];
    };
    
    Dinic dc;
    int row, col;
    int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
    
    bool check(int x, int y) {
        if (1 <= x && x <= row && 1 <= y && y <= col) {
            return true;
        }
        return false;
    }
    
    int main() {
        scanf("%d%d", &row, &col);
        int sum = 0;
        int s = 0, t = row*col + 1;
        dc.initdata(t + 1, s, t);
        for (int i = 1; i <= row; i++) {
            for (int j = 1; j <= col; j++) {
                int a;
                scanf("%d", &a);
                sum += a;
                if ((i+j) & 1)
                    dc.addedge((i-1)*col+j, t, a);
                else {
                    dc.addedge(s, (i-1)*col+j, a);
                    for (int k = 0; k < 4; k++) {
                        int x = i + dir[k][0];
                        int y = j + dir[k][1];
                        if (check(x, y))
                            dc.addedge((i-1)*col+j, (x-1)*col+y, INFS);
                    }
                }
            }
        }
        printf("%d\n", sum - dc.maxflow());
        return 0;
    }
  • 相关阅读:
    Maximum Depth of Binary Tree
    Single Number
    Merge Two Sorted Lists
    Remove Nth Node From End of List
    Remove Element
    Remove Duplicates from Sorted List
    Add Two Numbers
    编译视频直播点播平台EasyDSS数据排序使用Go 语言 slice 类型排序的实现介绍
    RTMP协议视频直播点播平台EasyDSS在Linux系统中以服务启动报错can’t evaluate field RootPath in type*struct排查
    【解决方案】5G时代RTMP推流服务器/互联网直播点播平台EasyDSS实现360°全景摄像机VR直播
  • 原文地址:https://www.cnblogs.com/kedebug/p/3033183.html
Copyright © 2011-2022 走看看