• LibreOJ #6008. 「网络流 24 题」餐巾计划 最小费用最大流 建图


    #6008. 「网络流 24 题」餐巾计划

    内存限制:256 MiB时间限制:1000 ms标准输入输出
    题目类型:传统评测方式:文本比较
    上传者: 匿名

    题目描述

    一个餐厅在相继的 n nn 天里,每天需用的餐巾数不尽相同。假设第 i ii 天需要 ri r_iri​​ 块餐巾。餐厅可以购买新的餐巾,每块餐巾的费用为 P PP 分;或者把旧餐巾送到快洗部,洗一块需 M MM天,其费用为 F FF 分;或者送到慢洗部,洗一块需 N NN 天,其费用为 S SS 分(S<F S < FS<F)。

    每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗。但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量。

    试设计一个算法为餐厅合理地安排好 n nn 天中餐巾使用计划,使总的花费最小。

    输入格式

    第 1 11 行有 6 66 个正整数 n nn、P PP、M MM、F FF、N NN、S SS。

    n nn 是要安排餐巾使用计划的天数,P PP 是每块新餐巾的费用,M MM 是快洗部洗一块餐巾需用天数,F FF 是快洗部洗一块餐巾需要的费用,N NN 是慢洗部洗一块餐巾需用天数,S SS 是慢洗部洗一块餐巾需要的费用。

    接下来的 n nn 行是餐厅在相继的 n nn 天里,每天需用的餐巾数。

    输出格式

    输出餐厅在相继的 n nn 天里使用餐巾的最小总花费。

    样例

    样例输入

    3 10 2 3 3 2
    5
    6
    7

    样例输出

    145

    数据范围与提示

    1≤n≤1000 1 leq n leq 10001n1000

    题目链接:https://loj.ac/problem/6008

    题意:中文一题,明显。

    思路:最小费用最大流。关键是怎样建图,每天的毛巾来源有购买、快洗部、慢洗部,每天用过的毛巾的去处有留到下一天、拿去快洗、拿去慢洗。

    建图:

    把每天分为二分图两个集合中的顶点Xi,Yi,分别表示用完的毛巾,需要的毛巾建立附加源S汇T。
    1、从S向每个Xi连一条容量为ri,费用为0的有向边。(用完的毛巾数量限制)
    2、从每个Yi向T连一条容量为ri,费用为0的有向边。(需要数量限制)
    3、从S向每个Yi连一条容量为无穷大,费用为P的有向边。(通过购买获得)
    4、从每个Xi向Xi+1(i+1<=n)连一条容量为无穷大,费用为0的有向边。(保存起来,延期送洗)
    5、从每个Xi向Yi+M(i+M<=n)连一条容量为无穷大,费用为F的有向边。(立即拿去快洗部,并可在M天后获得)
    6、从每个Xi向Yi+M(i+N<=n)连一条容量为无穷大,费用为S的有向边。(立即拿去慢洗部,并在N天后获得)
    求网络最小费用最大流,费用流值就是要求的最小总花费。

    代码:
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<vector>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    #define PI acos(-1.0)
    const int maxn=3e3+100,maxm=1e5+100,inf=0x3f3f3f3f,mod=1e9+7;
    const ll INF=1e13+7;
    struct edge
    {
        int from,to;
        int c,w;
    };
    vector<edge>es;
    vector<int>G[maxn];
    int pre[maxn];
    int dist[maxn];
    inline void addedge(int u,int v,int c,int w)
    {
        es.push_back((edge)
        {
            u,v,c,w
        });
        es.push_back((edge)
        {
            v,u,0,-w
        });
        int x=es.size();
        G[u].push_back(x-2);
        G[v].push_back(x-1);
    }
    
    bool spfa(int s,int t)
    {
        static std::queue<int> q;
        static bool inq[maxn];
        memset(dist,inf,sizeof(int)*maxn);
        memset(inq,false,sizeof(bool)*maxn);
        pre[s]=-1;
        dist[s]=0;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            inq[u]=false;
            for(int i=0; i<G[u].size(); i++)
            {
                edge e=es[G[u][i]];
                if(e.c&&dist[e.to]>dist[u]+e.w)
                {
                    pre[e.to]=G[u][i];
                    dist[e.to]=dist[u]+e.w;
                    if(!inq[e.to]) q.push(e.to),inq[e.to]=true;
                }
            }
        }
        return dist[t]<inf;
    }
    
    int dinic(int s,int t)
    {
        int flow=0,cost=0;
        while(spfa(s,t))
        {
            int d=inf;
            for(int i=t; i!=s; i=es[pre[i]].from)
                d=min(d,es[pre[i]].c);
            flow+=d;
            cost+=d*dist[t];
            for(int i=t; i!=s; i=es[pre[i]].from)
            {
                es[pre[i]].c-=d;
                es[pre[i]^1].c+=d;
            }
        }
        ///cout<<flow<<" "<<cost<<endl;///最小费用最大流的流量和花费
        return cost;
    }
    int main()
    {
        int n,P,N,F,M,S;
        scanf("%d%d%d%d%d%d",&n,&P,&N,&F,&M,&S);
        int s=0,t=2*n+1;
        for(int i=1; i<=n; i++)
        {
            int x;
            scanf("%d",&x);
            addedge(s,i,x,0);
            addedge(s,i+n,inf,P);
            if(i-1>=1) addedge(i-1,i,inf,0);
            if(i-N>=1) addedge(i-N,i+n,inf,F);
            if(i-M>=1) addedge(i-M,i+n,inf,S);
            addedge(i+n,t,x,0);
        }
        printf("%d
    ",dinic(s,t));
        return 0;
    }
    最小费用最大流
  • 相关阅读:
    方法
    属性
    Cocoapods完整使用篇
    这样好用的ReactiveCocoa,根本停不下来【转载】
    OS开发之旅之App的生命周期【转载】
    ios 推送证书没有密钥 解决方案【转载】
    移动应用开发测试工具Bugtags集成和使用教程【转载】
    MagicalRecord使用教程【转载】
    GIT客户端的使用【原创】
    iOS开发系列--让你的应用“动”起来【转载】
  • 原文地址:https://www.cnblogs.com/GeekZRF/p/7360233.html
Copyright © 2020-2023  润新知