不固定流量的最小费用流 生产销售规划 uva11613 - Acme Corporation

本文解析了UVa11613题目中的费用流算法实现细节,通过建立适当的网络模型,利用Bellman-Ford算法求解最小费用最大流问题,以计算公司最大利润。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2660

大白书p371

题意:Acme公司生产一种X元素。给出该元素在未来M个月中每个月的单位售价,最大产量,生产成本,最大销售量,以及最大存储时间,计算公司能获得的最大利润。

思路:费用流。可以将每个月拆成两个点,分别看成月生产和月销售。建立源点S和汇点T。从S向每个月生产点连一条容量为ni,费用为mi的弧,在从每个月销售点向T连一条容量为si,费用为-pi的弧。然后从每个月生产点向存储时间内的月销售点连一条容量为inf,费用为存储时间×I的弧。最后做费用流,当增广到最短路径大于0时停止增广即可。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 2139062143
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
//#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=200+100;
struct Edge
{
    ll from,to,cap,flow,cost;
};
struct MCFC
{
    vector<Edge>edges;
    vector<int>G[maxn];
    int m,n,s,t;
    ll d[maxn],inq[maxn],p[maxn],a[maxn];
    void Init(int n)
    {
        this->n=n;
        for(int i=0;i<=n;++i) G[i].clear();
        edges.clear();
    }
    void AddEdges(ll from,ll to,ll cap,ll cost)
    {
        edges.push_back((Edge){from,to,cap,0,cost});
        edges.push_back((Edge){to,from,0,0,-cost});
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    bool BellmanFord(ll s,ll t,ll & flow,ll & cost)
    {
        memset(inq,0,sizeof(inq));
        for(int i=0;i<=n;++i) d[i]=Inf;
        d[s]=0;p[s]=0;inq[s]=1;a[s]=Inf;
        queue<int>q;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();q.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]) {q.push(e.to);inq[e.to]=1;}
                }
            }
        }
        if(d[t]>0) 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;
    }
    ll Mincost(int s,int t)
    {
        ll flow=0,cost=0;
        while(BellmanFord(s,t,flow,cost));
        return cost;
    }
}mcfc;
struct MonInfo
{
    int mi,ni,pi,si,E;
};
MonInfo mon[maxn];
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t,tcase=0;
    scanf("%d",&t);
    while(t--)
    {
        tcase++;
        int M,I;
        scanf("%d%d",&M,&I);
        int N=2*M+1;
        mcfc.Init(N);
        for(int i=1;i<=M;++i)
          scanf("%d%d%d%d%d",&mon[i].mi,&mon[i].ni,&mon[i].pi,&mon[i].si,&mon[i].E);
        for(int i=1;i<=M;++i)
        {
            mcfc.AddEdges(0,i,mon[i].ni,mon[i].mi);
            int z=min(M,mon[i].E+i);
            for(int j=i;j<=z;++j)
            {
                mcfc.AddEdges(i,M+j,Inf,(j-i)*I);
            }
        }
        for(int i=1;i<=M;++i)
           mcfc.AddEdges(i+M,N,mon[i].si,-mon[i].pi);
        ll ans=mcfc.Mincost(0,N);
        printf("Case %d: %lld\n",tcase,-ans);
    }
    return 0;
}

// UVa11613 Acme Corporation
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<cassert>
using namespace std;

const int maxn = 202 + 10;
const int INF = 1000000000;

typedef long long LL;

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];           // Bellman-Ford
  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((Edge){from, to, cap, 0, cost});
    edges.push_back((Edge){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& ans) {
    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> Q;
    Q.push(s);
    while(!Q.empty()) {
      int u = Q.front(); Q.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]) { Q.push(e.to); inq[e.to] = 1; }
        }
      }
    }
    if(d[t] > 0) return false;
    ans += (LL)d[t] * (LL)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;
  }

  // 需要保证初始网络中没有负权圈
  LL Mincost(int s, int t) {
    LL cost = 0;
    while(BellmanFord(s, t, cost));
    return cost;
  }

};

MCMF g;

int main() {
  int T, month, store_cost;
  scanf("%d", &T);
  for(int kase = 1; kase <= T; kase++) {
    scanf("%d%d", &month, &store_cost);
    g.init(2*month+2);
    int source = 0, sink = 2*month+1;
    for(int i = 1; i <= month; i++) {
      int make_cost, make_limit, price, sell_limit, max_store;
      scanf("%d%d%d%d%d", &make_cost, &make_limit, &price, &sell_limit, &max_store);
      g.AddEdge(source, i, make_limit, make_cost);
      g.AddEdge(month+i, sink, sell_limit, -price); // 收益是负费用
      for(int j = 0; j <= max_store; j++) if(i + j <= month)
        g.AddEdge(i, month+i+j, INF, store_cost * j); // 存j个月以后卖
    }
    printf("Case %d: %lld\n", kase, -g.Mincost(source, sink));
  }
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值