zoukankan      html  css  js  c++  java
  • BZOJ 2424 订货 最小费用流

    题目链接:

    https://www.lydsy.com/JudgeOnline/problem.php?id=2424

    题目大意:

    某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为零,问如何安排这n个月订购计划,才能使成本最低?每月月初订购,订购后产品立即到货,进库并供应市场,于当月被售掉则不必付存贮费。假设仓库容量为S。

    思路:

    直接建图即可。

    对于每个月i,从s->i 容量为INF,因为可以购买任意数量的产品,费用为d[i],为当月售价

    从i->t容量为U[i],因为需要出售这么多,费用为0,因为出售不需要费用。

    i->i+1 容量为S,因为仓库容量为S,费用为m,因为上月留下来的单位产品的费用为m

      1 #include<bits/stdc++.h>
      2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
      3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
      4 #define Min(a, b) ((a) < (b) ? (a) : (b))
      5 #define Mem(a) memset(a, 0, sizeof(a))
      6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
      7 #define MID(l, r) ((l) + ((r) - (l)) / 2)
      8 #define lson ((o)<<1)
      9 #define rson ((o)<<1|1)
     10 #define Accepted 0
     11 #pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
     12 using namespace std;
     13 inline int read()
     14 {
     15     int x=0,f=1;char ch=getchar();
     16     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
     17     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     18     return x*f;
     19 }
     20 
     21 typedef long long ll;
     22 const int maxn = 100 + 10;
     23 const int MOD = 1000000007;//const引用更快,宏定义也更快
     24 const int INF = 1e9 + 7;
     25 const double eps = 1e-6;
     26 
     27 struct edge
     28 {
     29     int u, v, c, f, cost;
     30     edge(int u, int v, int c, int f, int cost):u(u), v(v), c(c), f(f), cost(cost){}
     31 };
     32 vector<edge>e;
     33 vector<int>G[maxn];
     34 int a[maxn];//找增广路每个点的水流量
     35 int p[maxn];//每次找增广路反向记录路径
     36 int d[maxn];//SPFA算法的最短路
     37 int inq[maxn];//SPFA算法是否在队列中
     38 int n, m;
     39 void init(int n)
     40 {
     41     for(int i = 0; i <= n; i++)G[i].clear();
     42     e.clear();
     43 }
     44 void addedge(int u, int v, int c, int cost)
     45 {
     46     e.push_back(edge(u, v, c, 0, cost));
     47     e.push_back(edge(v, u, 0, 0, -cost));
     48     int m = e.size();
     49     G[u].push_back(m - 2);
     50     G[v].push_back(m - 1);
     51 }
     52 bool bellman(int s, int t, int& flow, long long & cost)
     53 {
     54     for(int i = 0; i <= n + 2; i++)d[i] = INF;//Bellman算法的初始化
     55     memset(inq, 0, sizeof(inq));
     56     d[s] = 0;inq[s] = 1;//源点s的距离设为0,标记入队
     57     p[s] = 0;a[s] = INF;//源点流量为INF(和之前的最大流算法是一样的)
     58 
     59     queue<int>q;//Bellman算法和增广路算法同步进行,沿着最短路拓展增广路,得出的解一定是最小费用最大流
     60     q.push(s);
     61     while(!q.empty())
     62     {
     63         int u = q.front();
     64         q.pop();
     65         inq[u] = 0;//入队列标记删除
     66         for(int i = 0; i < G[u].size(); i++)
     67         {
     68             edge & now = e[G[u][i]];
     69             int v = now.v;
     70             if(now.c > now.f && d[v] > d[u] + now.cost)
     71                 //now.c > now.f表示这条路还未流满(和最大流一样)
     72                 //d[v] > d[u] + e.cost Bellman 算法中边的松弛
     73             {
     74                 d[v] = d[u] + now.cost;//Bellman 算法边的松弛
     75                 p[v] = G[u][i];//反向记录边的编号
     76                 a[v] = min(a[u], now.c - now.f);//到达v点的水量取决于边剩余的容量和u点的水量
     77                 if(!inq[v]){q.push(v);inq[v] = 1;}//Bellman 算法入队
     78             }
     79         }
     80     }
     81     if(d[t] == INF)return false;//找不到增广路
     82     flow += a[t];//最大流的值,此函数引用flow这个值,最后可以直接求出flow
     83     cost += (long long)d[t] * (long long)a[t];//距离乘上到达汇点的流量就是费用
     84     for(int u = t; u != s; u = e[p[u]].u)//逆向存边
     85     {
     86         e[p[u]].f += a[t];//正向边加上流量
     87         e[p[u] ^ 1].f -= a[t];//反向边减去流量 (和增广路算法一样)
     88     }
     89     return true;
     90 }
     91 int MincostMaxflow(int s, int t, long long & cost)
     92 {
     93     cost = 0;
     94     int flow = 0;
     95     while(bellman(s, t, flow, cost));//由于Bellman函数用的是引用,所以只要一直调用就可以求出flow和cost
     96     return flow;//返回最大流,cost引用可以直接返回最小费用
     97 }
     98 int u[maxn], b[maxn];
     99 int main()
    100 {
    101     int s;
    102     scanf("%d%d%d", &n, &m, &s);
    103     for(int i = 1; i <= n; i++)scanf("%d", &u[i]);
    104     for(int i = 1; i <= n; i++)scanf("%d", &b[i]);
    105     for(int i = 1; i <= n; i++)
    106     {
    107         addedge(0, i, INF, b[i]);
    108         addedge(i, n + 1, u[i], 0);
    109     }
    110     for(int i = 1; i < n; i++)addedge(i, i + 1, s, m);
    111     ll cost = 0;
    112     MincostMaxflow(0, n + 1, cost);
    113     printf("%lld
    ", cost);
    114     return Accepted;
    115 }
  • 相关阅读:
    跳出iframe
    leetcode 225. Implement Stack using Queues
    leetcode 206. Reverse Linked List
    leetcode 205. Isomorphic Strings
    leetcode 203. Remove Linked List Elements
    leetcode 198. House Robber
    leetcode 190. Reverse Bits
    leetcode leetcode 783. Minimum Distance Between BST Nodes
    leetcode 202. Happy Number
    leetcode 389. Find the Difference
  • 原文地址:https://www.cnblogs.com/fzl194/p/9684277.html
Copyright © 2011-2022 走看看