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
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Qt 自定义model实现文件系统的文件名排序
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8120015.html
Copyright © 2011-2022 走看看