Acme Corporation UVA - 11613 (最小费用最大流)题解


Wile E. Coyote is back. He is back in the business.The business of capturing the road runner.Being the most loyal customer to the AcmeCorporation, they are hoping to do some great business with him. Although, Acme makes literallyevery kinds of devices, all of them has asimilarity, that has been kept secret for ages. Allof their products use a secret element “element X” (this is kept so secret that, only you and theAcme people know about this). The decision
makers of the Acme Corp. has already estimated the maximum amount of element X that can beused into manufacture every month.For month i, the per unit manufacturing cost
of “element X” is mi, and at most ni units can
be produced. Moreover, the selling price for “element X” for that month is pi. One more thing is that, element X older than Ei months can not be used. But good thing is that, they can store
any amount of element X in their inventory (it’s the Acme Corp, they can make anything :) ).Now, Acme Corporation wants to know how much element X should be produced and sold, to make the highest amount of profit.
Input
• First line contains T, the number of test
cases.
• For each test case
– First line contains two integers M and I, the number of months to consider and the cost of
storing per unit of element X per month in the inventory.
– Each of the next M lines describe the parameters for each month
∗ The i-th line contains 5 integers, mi, ni, pi, si, Ei, where mi
is the per unit manufacturing cost for month i, ni
is the maximum amount that can be manufactured in this
month, pi is the selling price for that month (per unit), si
is the maximum amount that can be sold that month, and Ei
is the maximum time, element X manufactured on month i, can be stored in the inventory. For example, if for month 1, E1 = 3, the
elements produced in month 1 can be sold in months 1, 2, 3 and 4. But it can not be sold in month 5.
Output
For each test case, output the case number and the maximum amount of profit, Acme Corporation can
make. Note that, you have to think of only M months. If any amount of element X is stored in the
inventory after this period, are completely ignored. For formatting, see the sample input and output.
Constraints
• T ≤ 100
• M ≤ 100
• 0 ≤ I, mi
, ni
, pi
, si ≤ 106
• 0 ≤ Ei ≤ M
Sample Input
1
2 2
2 10 3 20 2
10 100 7 5 2
Sample Input
Case 1: 2


问题简单来说就是生产商品,贮存和出售的故事。每月有最大生产量,单位生产成本,货物最大贮存时间,最大销售量,单位售价,贮存费用。要求的最大的获利。以每个月的生产建一个点,销售建一个点,则源点到生产点的边容量为最大产量费用为该月单位生产成本,销售点连到汇点为容量为最大销售量费用为单位售价,生产点连到销售点为把这个月的产品放到第j个月出售,容量为inf费用为贮存成本,把所有费用取负,就变成了求最小费用最大流。

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<vector>
#include<string>
#include<queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxe = 30005;
const int maxk = 505;
const int mod = 1000000000;
const int maxn = 500;
int n, m, k;
struct  edge{
    int from, to, cap, flow,cost;
};

struct MCMF{
    int n, m, s, t;
    vector<edge> edges;
    vector<int> G[maxn];
    int inq[maxn];
    int d[maxn];
    int p[maxn];
    int a[maxn];

    void init(int n){
        this->n = n;
        for (int i = 0; i < n; i++){
            G[i].clear();
        }
        edges.clear();
    }

    void addedge(int from, int to, int cap, int cost){
        edges.push_back({ from, to, cap, 0, cost });
        edges.push_back({ to, from, 0, 0, -cost });
        m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }

    bool bellmanford(int s, int t, ll &flow, ll &cost){
        //for (int i = 0; i < n; i++){d[i]=inf;}
        memset(d, 0x3f, sizeof(d));
        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] = 0;
            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]){ que.push(e.to); inq[e.to] = 1; }
                }
            }
        }
        if (d[t] >0)return 0;
        flow += a[t];
        cost += (ll)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 1;
    }

    ll mincost(int s, int t){
        ll flow = 0, cost = 0;
        while (bellmanford(s, t, flow, cost));
        return cost;
        //return flow;
    }

}mcmf;


int main(){
    int t,a,b,c,d,e;
    scanf("%d", &t);
    for (int cas = 1; cas <= t; cas++){
        scanf("%d%d", &n, &m);
        int T = 2 * n + 2, S = 2 * n + 1;
        mcmf.init(2*n+3);
        for (int i = 0; i < n; i++){
            scanf("%d%d%d%d%d", &a, &b, &c, &d, &e);
            mcmf.addedge(S, i, b, a);
            mcmf.addedge(i + n, T, d, -c);
            for (int j = i; j <= i+e&&j<n; j++){
                mcmf.addedge(i, n + j, inf, m*(j-i));
            }
        }
        ll ans = -mcmf.mincost(S, T);
        printf("Case %d: %lld\n",cas ,ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值