zoukankan      html  css  js  c++  java
  • UVA11613 Acme Corporation —— 最小费用流(流量不固定的最小费用流)

    题目链接:https://vjudge.net/problem/UVA-11613

     

    题意:

    商品X在第i个月内:生产一件需要花费mi元,最多可生产ni件,销售一件(在这个月内销售,而不管它是在那个月生产的)的价格是pi元, 最多能销售si件, 在这个月生产的产品的保质期为Ei。对于所有商品X,每“保质”一个月,就要花费I元。问:在M个月内,最多能获利多少?

    题解:

    最小费用流问题,建图方式如下(详情在《训练指南》P367):

    1.把每个月拆成两个点,一个点为生产,另一个点为销售。

    2.如果月x生产的商品能够放到月y内销售,就在月x的生产点和月y的销售点之间连一条边,容量为月x的最大生产量, 花费为0。

    3.建立超级源点,并且连向每个月的生产点,边的容量为该月的最大生产量, 边的花费为该月生产一件商品所需的花费。

    4.建立超级汇点,并且连向每个月的销售点,边的容量为该月的最大销售量, 边的花费为该月单间商品的售价的负值

    5.跑最小费用流算法:当增广得到的单位费用和小于0时,表明收入大于敷出(因为收入在图中设置为负值),继续增广;当单位费用和大于等于0时,表明收入小于敷出,再继续增广,利润反而降低,所以在此时就应该停止增广。

    代码如下:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <cmath>
      7 #include <queue>
      8 #include <stack>
      9 #include <map>
     10 #include <string>
     11 #include <set>
     12 using namespace std;
     13 typedef long long LL;
     14 const int INF = 2e9;
     15 const LL LNF = 9e18;
     16 const int mod = 1e9+7;
     17 const int MAXM = 1e5+10;
     18 const int MAXN = 2e2+10;
     19 
     20 struct Edge
     21 {
     22     int to, next, cap, flow, cost;
     23 }edge[MAXM];
     24 int tot, head[MAXN];
     25 int pre[MAXN], dis[MAXN];
     26 bool vis[MAXN];
     27 int N;
     28 
     29 void init(int n)
     30 {
     31     N = n;
     32     tot = 0;
     33     memset(head, -1, sizeof(head));
     34 }
     35 
     36 void add(int u, int v, int cap, int cost)
     37 {
     38     edge[tot].to = v;  edge[tot].cap = cap;  edge[tot].cost = cost;
     39     edge[tot].flow = 0;   edge[tot].next = head[u];   head[u] = tot++;
     40     edge[tot].to = u;   edge[tot].cap = 0;  edge[tot].cost = -cost;
     41     edge[tot].flow = 0; edge[tot].next = head[v];   head[v] = tot++;
     42 }
     43 
     44 bool spfa(int s, int t)
     45 {
     46     queue<int>q;
     47     for(int i = 0; i<N; i++)
     48     {
     49         dis[i] = INF;
     50         vis[i] = false;
     51         pre[i] = -1;
     52     }
     53 
     54     dis[s] = 0;
     55     vis[s] = true;
     56     q.push(s);
     57     while(!q.empty())
     58     {
     59         int u  = q.front();
     60         q.pop();
     61         vis[u] = false;
     62         for(int i = head[u]; i!=-1; i = edge[i].next)
     63         {
     64             int v = edge[i].to;
     65             if(edge[i].cap>edge[i].flow && dis[v]>dis[u]+edge[i].cost)
     66             {
     67                 dis[v] = dis[u]+edge[i].cost;
     68                 pre[v] = i;
     69                 if(!vis[v])
     70                 {
     71                     vis[v] = true;
     72                     q.push(v);
     73                 }
     74             }
     75         }
     76     }
     77     if(pre[t]==-1) return false;
     78     if(dis[t]>=0) return false; //当单位费用和大于等于0时,即停止增广
     79     return true;
     80 }
     81 
     82 int minCostMaxFlow(int s, int t, LL &cost)
     83 {
     84     int flow = 0;
     85     cost = 0;
     86     while(spfa(s,t))
     87     {
     88         int Min = INF;
     89         for(int i = pre[t]; i!=-1; i = pre[edge[i^1].to])
     90         {
     91             if(Min>edge[i].cap-edge[i].flow)
     92                 Min = edge[i].cap-edge[i].flow;
     93         }
     94         for(int i = pre[t]; i!=-1; i = pre[edge[i^1].to])
     95         {
     96             edge[i].flow += Min;
     97             edge[i^1].flow -= Min;
     98             cost += 1LL*edge[i].cost*Min;
     99         }
    100         flow += Min;
    101     }
    102     return flow;
    103 }
    104 
    105 int main()
    106 {
    107     int T, M, I;
    108     scanf("%d", &T);
    109     for(int kase = 1; kase<=T; kase++)
    110     {
    111         scanf("%d%d", &M, &I);
    112         int start = 0, end = 2*M+1;
    113         init(2*M+2);
    114 
    115         for(int i = 1; i<=M; i++)
    116         {
    117             int m, n, p, s, E;
    118             scanf("%d%d%d%d%d", &m,&n,&p,&s,&E);
    119             add(start, i, n, m);
    120             for(int j = i; j<=min(M, i+E); j++)
    121                 add(i, M+j, n, (j-i)*I);
    122             add(M+i, end, s, -p);
    123         }
    124 
    125         LL min_cost;
    126         minCostMaxFlow(start, end, min_cost);
    127         printf("Case %d: %lld
    ", kase, -min_cost);
    128     }
    129 }
    View Code
  • 相关阅读:
    iOS开发——判断是否第一次启动
    iOS开发——关于开发者账号引发的血案
    The identity used to sign the executable is no longer valid.
    iOS开发 missing iOS distribution signing identity for 。。。
    iOS开发实现Label中多颜色多字体
    10.8.5如何升级(app store 出错 请稍后重试 100)
    XCode 7上传遇到ERROR ITMS-90535 Unexpected CFBundleExecutable Key. 的解决办法
    mysql索引的类型和优缺点
    .htaccess Rewrite apache重写和配置
    mysql xtrabackup 备份恢复实现,mysql命令备份数据库,打包压缩数据库
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8120015.html
Copyright © 2011-2022 走看看