• 网络流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;
    }
  • 相关阅读:
    第十二周作业
    十一周作业
    第十周作业
    第九周作业
    2019年春第八周作业
    第五周课程总结&实验报告(三)
    第四周课程总结&实验报告(二)
    第三周课程总结&实验报告(一)
    第二周课程总结
    2019春总结作业
  • 原文地址:https://www.cnblogs.com/kedebug/p/3033183.html
Copyright © 2020-2023  润新知