zoukankan      html  css  js  c++  java
  • 网络流24题(10)餐巾计划问题(最小费用最大流)

    思路:

    1. 把每天分成两个集:Xi(第 i 天用剩的餐巾),Yi(第 i 天需要的餐巾)

    2. s 向 X 引弧,容量为 ri,费用为 0;Y 向 t 引弧,容量为 ri,费用为 0;s 向 Y 引弧,容量为无穷大,费用为 p

    3. 由于每天用剩下的餐巾可以分为下面三种情况:

       a. 什么也不做,留着当做第二天的旧餐巾: Xi 向 Xi+1 引弧,容量为无穷大,费用为 0;

       b. 送给快洗部,相当于:Xi 向 Yi+m 引弧,容量为无穷大,费用为 f;

       c. 送给慢洗部,相当于:Xi 向 Yi+n 引弧,容量为无穷大,费用为 s;

    4. 求上面二分图的最小费用最大流,因为最大流一定能保证 Yi->t 为满弧,满足约束条件。最小的费用即是要输出的结果。

    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <vector>
    using namespace std;
    
    const int MAXN = 2010;
    const int INFS = 0x3FFFFFFF;
    
    struct edge {
        int from, to, cap, flow, cost;
        edge(int _from, int _to, int _cap, int _flow, int _cost)
            : from(_from), to(_to), cap(_cap), flow(_flow), cost(_cost) {}
    };
    
    class MCMF {
    public:
        void initdata(int n) {
            this->n = n;
            edges.clear();
            for (int i = 0; i < n; i++)
                G[i].clear();
        }
        void addedge(int u, int v, int cap, int cost) {
            edges.push_back(edge(u, v, cap, 0, cost));
            edges.push_back(edge(v, u, 0, 0, -cost));
            G[u].push_back(edges.size() - 2);
            G[v].push_back(edges.size() - 1);
        }
    
        bool SPFA(int s, int t, int& flow, int& cost) {
            for (int i = 0; i < n; i++)
                d[i] = INFS, inq[i] = false;
            queue<int> Q;
            Q.push(s);
            d[s] = 0, inq[s] = true, p[s] = 0, a[s] = INFS;
            while (!Q.empty()) {
                int u = Q.front(); Q.pop();
                inq[u] = false;
                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] = true;
                            Q.push(e.to);
                        }
                    }
                }
            }
            if (d[t] == INFS) return false;
            flow += a[t];
            cost += a[t] * d[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 mincost(int s, int t) {
            int flow = 0, cost = 0;
            while (SPFA(s, t, flow, cost));
            return cost;
        }
    private:
        vector<edge> edges;
        vector<int> G[MAXN];
        int n, d[MAXN], p[MAXN], a[MAXN];
        bool inq[MAXN];
    };
    
    MCMF mcmf;
    
    int main() {
        int n, cost;
        int fast, fastcost, slow, slowcost;
        scanf("%d%d", &n, &cost);
        scanf("%d%d", &fast, &fastcost);
        scanf("%d%d", &slow, &slowcost);
        int s = 0, t = 2*n+1;
        mcmf.initdata(t + 1);
        for (int i = 1; i <= n; i++) {
            int need;
            scanf("%d", &need);
            mcmf.addedge(s, i, need, 0);
            mcmf.addedge(i+n, t, need, 0);
            mcmf.addedge(s, i+n, INFS, cost);
        }
        for (int i = 1; i <= n; i++) {
            if (i + 1 <= n)
                mcmf.addedge(i, i+1, INFS, 0);
            if (i + fast <= n)
                mcmf.addedge(i, i+n+fast, INFS, fastcost);
            if (i + slow <= n)
                mcmf.addedge(i, i+n+slow, INFS, slowcost);
        }
        printf("%d\n", mcmf.mincost(s, t));
        return 0;
    }
  • 相关阅读:
    webdav srs相关
    How To Configure WebDAV Access with Apache on Ubuntu 14.04
    ubuntu 编译lighttpd
    srs编译及推流测试
    Compile pciutils (lspci, setpci) in Windows x86,在 Windows x86 平台下编译 pciutils (lspci, setpci)
    mingw MSYS2 区别
    Qt之美(三):隐式共享
    Qt之美(二):元对象
    Qt之美(一):d指针/p指针详解
    C++的栈空间和堆空间
  • 原文地址:https://www.cnblogs.com/kedebug/p/3043748.html
Copyright © 2011-2022 走看看