# 6010. "24 network flow problem" digital keystone to build the largest cost maximum flow chart

Topic Link
meaning of the questions
Here Insert Picture Description
are required to meet the conditions of all three rules and maximum paths.
Thinking
network flow problem is to build the most important graph problems.
1. disjoint paths, i.e. a digital only be used once, and that is the split point, each point of the split and out points, and even a capacity between the point and the out point of a cost is the weight side; establishing a source and a sink, connected to the point source from the first row, a capacity of 1 0 cost, and finally connected to the node and sink line, a capacity of 1 0 cost, in addition to the last line in addition, each point to point out the point directly below it and the lower right even a capacity of 1 0 cost side. Then run the largest cost maximum flow.
2. Digital node can intersect, then the point of each node connected to the edge capacity points instead INF, costs the same, you can only take a cancellation point limits, as well as point out the last line and sinks INF capacity even point cost side 0, and then also run the largest direct cost maximum flow.
3. edges and points can intersect, that is, the removal of restrictions between the dots, on the basis of the edge of the construction on the second question of the point directly below it and the first question in the lower right of each point capacity point changed INF, cost or zero.

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 5e3 + 7;
const int M = 1e4 + 7;
typedef long long ll;
int maxflow, maxcost;
struct Edge {
    int from, to, cap, flow, cost;
    Edge(int u, int v, int ca, int f, int co):from(u), to(v), cap(ca), flow(f), cost(co){};
};
struct MCMF
{
    int n, m, s, t;
    vector<Edge> edges;
    vector<int> G[N];
    int inq[N], d[N], p[N], a[N];//是否在队列 距离 上一条弧 可改进量
    void init(int n) {
        this->n = n;
        for (int i = 0; i < n; i++) G[i].clear();
        edges.clear();
    }
    void add(int from, int to, int cap, int cost) {
        edges.push_back(Edge(from, to, cap, 0, cost));
        edges.push_back(Edge(to, from, 0, 0, -cost));
        int m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }
    bool SPFA(int s, int t, int &flow, int &cost) {
        for (int i = 0; i < N; i++) d[i] = -INF;
        memset(inq, 0, sizeof(inq));
        d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
        queue<int> que;
        que.push(s);
        while (!que.empty()) {
            int u = que.front();
            que.pop();
            inq[u]--;
            for (int i = 0; i < G[u].size(); i++) {
                Edge& e = edges[G[u][i]];
                if(e.cap > e.flow && d[e.to] < d[u] + e.cost) {
                    d[e.to] = d[u] + e.cost;
                    p[e.to] = G[u][i];
                    a[e.to] = min(a[u], e.cap - e.flow);
                    if(!inq[e.to]) {
                        inq[e.to]++;
                        que.push(e.to);
                    }
                }
            }
        }
        if(d[t] == -INF) return false;
        flow += a[t];
        cost += d[t] * a[t];
        int u = t;
        while (u != s) {
            edges[p[u]].flow += a[t];
            edges[p[u]^1].flow -= a[t];
            u = edges[p[u]].from;
        }
        return true;
    }
    int MaxMaxflow(int s, int t) {
        int flow = 0, cost = 0;
        while (SPFA(s, t, flow, cost));
        maxflow = flow; maxcost = cost;
        return cost;
    }
};
int id[50][50], val[50][50];
int main()
{
    int m, n, s, t, tmp;
    MCMF solve;
    scanf("%d%d", &m, &n);
    s = 0; tmp = n * (2 * m + n - 1) / 2; t = tmp * 2 + 1;
    int tot = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m + i - 1; j++) {
            id[i][j] = ++tot;
            scanf("%d", &val[i][j]);
        }
    }
    //1
    for (int i = 1; i <= m; i++) solve.add(s, i, 1, 0);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m + i - 1; j++) {
            solve.add(id[i][j], id[i][j] + tmp, 1, val[i][j]);
            if(i != n) {
                solve.add(id[i][j] + tmp, id[i + 1][j], 1, 0);
                solve.add(id[i][j] + tmp, id[i + 1][j + 1], 1, 0);
            }
            if(i == n) {
                solve.add(id[i][j] + tmp, t, 1, 0);
            }
        }
    }
    solve.MaxMaxflow(s, t);
    printf("%d\n", maxcost);
    //2
    solve.init(N);
    for (int i = 1; i <= m; i++) solve.add(s, i, 1, 0);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m + i - 1; j++) {
            solve.add(id[i][j], id[i][j] + tmp, INF, val[i][j]);
            if(i != n) {
                solve.add(id[i][j] + tmp, id[i + 1][j], 1, 0);
                solve.add(id[i][j] + tmp, id[i + 1][j + 1], 1, 0);
            }
            if(i == n) {
                solve.add(id[i][j] + tmp, t, INF, 0);
            }
        }
    }
    solve.MaxMaxflow(s, t);
    printf("%d\n", maxcost);
    //3
    solve.init(N);
    for (int i = 1; i <= m; i++) solve.add(s, i, 1, 0);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m + i - 1; j++) {
            solve.add(id[i][j], id[i][j] + tmp, INF, val[i][j]);
            if(i != n) {
                solve.add(id[i][j] + tmp, id[i + 1][j], INF, 0);
                solve.add(id[i][j] + tmp, id[i + 1][j + 1], INF, 0);
            }
            if(i == n) {
                solve.add(id[i][j] + tmp, t, INF, 0);
            }
        }
    }
    solve.MaxMaxflow(s, t);
    printf("%d\n", maxcost);
}

Published 27 original articles · won praise 2 · Views 1980

Guess you like

Origin blog.csdn.net/D_Bamboo_/article/details/104091725