餐巾计划问题【网络流24题】【最大流最小费用】

版权声明:https://blog.csdn.net/qq_41730082 https://blog.csdn.net/qq_41730082/article/details/88756494

题目链接


  一道普通的最大流最小费用的题,我们需要考虑的是这样的情况:第i天的旧餐巾我们该怎么处理?我们知道可以退后m天去快洗,然后在第i+m天再次使用它花费f元,另外的方法就是在推后n天去慢洗,花费的s元,但是我们要是遇到刚好那天在这段区间内的怎么办,我们不如就加上一组无条件推后一天的情况。

  那么,我们可以这么去建边,从源点开始,连上一天流量为当天使用的旧餐巾的数目的边,再连上一天流量为INF的到定义的新餐巾的边其需要的钱是p(买一个新餐巾的价钱),然后,我们知道有“推迟一天”、“快洗m天”、“慢洗n天”这样的情况,我们就由旧餐巾连向x天后的对应的新餐巾,然后由新餐巾向汇点连接上对应的每天需要的餐巾的数目。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxE = 1.2e4 + 7, maxN = 6007, S = 0;
int N, p, m, f, n, s, head[maxN], cnt, pre[maxN], r[maxN], T, Flow[maxN];
ll dist[maxN];
bool inque[maxN];
struct Eddge
{
    int nex, u, v, flow, cost;
    Eddge(int a=-1, int b=0, int c=0, int d=0, int f=0):nex(a), u(b), v(c), flow(d), cost(f) {}
}edge[maxE<<1];
inline void addEddge(int u, int v, int flow, int cost)
{
    edge[cnt] = Eddge(head[u], u, v, flow, cost);
    head[u] = cnt++;
}
queue<int> Q;
bool spfa()
{
    memset(pre, -1, sizeof(pre));   memset(dist, INF, sizeof(dist));    memset(Flow, 0, sizeof(Flow));  memset(inque, false, sizeof(inque));
    while(!Q.empty()) Q.pop();
    Q.push(S);  dist[S] = 0;    Flow[S] = INF;  inque[S] = true;
    while(!Q.empty())
    {
        int u = Q.front();  Q.pop();    inque[u] = false;
        for(int i=head[u], v, flow, cost; ~i; i=edge[i].nex)
        {
            v = edge[i].v; flow = edge[i].flow;    cost = edge[i].cost;
            if(flow && dist[v] > dist[u] + cost)
            {
                dist[v] = dist[u] + cost;
                pre[v] = i;
                Flow[v] = min(flow, Flow[u]);
                if(!inque[v])
                {
                    inque[v] = true;
                    Q.push(v);
                }
            }
        }
    }
    return pre[T] ^ -1;
}
ll Out_put()
{
    ll ans = 0;
    while(spfa())
    {
        int now = T, last = pre[now];
        while(now)
        {
            edge[last].flow -= Flow[T];
            edge[last^1].flow += Flow[T];
            now = edge[last].u;
            last = pre[now];
        }
        ans += (ll)Flow[T] * dist[T];
    }
    return ans;
}
inline void init()
{
    cnt = 0;    T = (N<<1) | 1;
    memset(head, -1, sizeof(head));
}
int main()
{
    scanf("%d", &N);
    init();
    for(int i=1; i<=N; i++) scanf("%d", &r[i]);
    scanf("%d%d%d%d%d", &p, &m, &f, &n, &s);
    for(int i=1; i<=N; i++)
    {
        addEddge(S, i, r[i], 0);    //旧的
        addEddge(i, S, 0, 0);
        addEddge(S, i + N, INF, p); //新的(也以其作为中间的中转站,用来继承旧的也可以)
        addEddge(i + N, S, 0, -p);
        addEddge(i + N, T, r[i], 0);    //到汇点
        addEddge(T, i + N, 0, 0);
        if(i + 1 + m <= N)  //延后去洗
        {
            addEddge(i, i + 1, INF, 0);
            addEddge(i + 1, i, 0, 0);
        }
        if(i + m <= N)  //快洗
        {
            addEddge(i, i + m + N, INF, f);
            addEddge(i + m + N, i, 0, -f);
        }
        if(i + n <= N)
        {
            addEddge(i, i + n + N, INF, s);
            addEddge(i + n + N, i, 0, -s);
        }
    }
    printf("%lld\n", Out_put());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/88756494
今日推荐