[cogs461] [网络流24题#10] 餐巾 [网络流,最小费用最大流]

建图:从源点向第一层连边,第一层表示当天用掉多少餐巾,第二层表示当天需要多少餐巾,所以注意购买餐巾的边容量为无穷大,要从源点开始连向第二层的点,每天可能有剩余,在第一层内表示为流入第二天的节点。具体见代码,第一次写费用流,不知道模板对不对。。。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <queue>

using namespace std;

template<const int _n,const int _m>
struct Edge
{
    struct Edge_base { int    to,next,w,c; }e[_m];
    int    cnt,p[_n];
    Edge() { clear(); }
    int    start(const int x) { return p[x]; }
    void    insert(const int x,const int y,const int z,const int zz)
    { e[++cnt].to=y; e[cnt].next=p[x]; e[cnt].w=z; e[cnt].c=zz; p[x]=cnt; return ; }
    void    clear() { cnt=1,memset(p,0,sizeof(p)); }
    Edge_base&    operator[](const int x) { return e[x]; }
};

int    n,Dis[110000],SSS,TTT,cur[110000],a[110000];
int    Cost,Flow;
bool    visited[110000];
Edge<110000,210000>    e;

bool    Spfa(const int S)
{
    int    i,t,temp;
    queue<int>    Q;
    memset(Dis,0x3f,sizeof(Dis));
    Dis[S]=0;
    visited[S]=true;
    Q.push(S);
    while(!Q.empty())
    {
        t=Q.front(),Q.pop();visited[t]=false;
        for(i=e.start(t);i;i=e[i].next)
        {
            temp=e[i].to;
            if(e[i].w && Dis[t]+e[i].c<Dis[temp])
            {
                Dis[temp]=Dis[t]+e[i].c;
                if(!visited[temp])
                {
                    visited[temp]=true;
                    Q.push(temp);
                }
            }
        }
    }
    return Dis[TTT]!=0x3f3f3f3f;
}

int    Dfs(const int S,const int bk)
{
    if(S==TTT)return bk;
    visited[S]=true;
    int    rest=bk;
    for(int &i=cur[S];i;i=e[i].next)
    {
        if(!visited[e[i].to] && Dis[S]+e[i].c==Dis[e[i].to] && e[i].w)
        {
            int    flow=Dfs(e[i].to,min(rest,e[i].w));
            Cost+=flow*e[i].c;
            e[i].w-=flow;
            e[i^1].w+=flow;
            if((rest-=flow)<=0)break;
        }
    }
    if(bk==rest)Dis[S]=0x3f3f3f3f;
    visited[S]=false;
    return bk-rest;
}

pair<int,int>    Dinic()
{
    while(Spfa(SSS))
    {
        memcpy(cur,e.p,sizeof(cur));
        Flow+=Dfs(SSS,0x3f3f3f3f);
    }
    return make_pair(Flow,Cost);
}

int main()
{
    freopen("napkin.in","r",stdin);
    freopen("napkin.out","w",stdout);
    int    i,newn,ts,cs,tf,cf;

    scanf("%d",&n);
    for(i=1;i<=n;++i)scanf("%d",&a[i]);
    scanf("%d%d%d%d%d",&newn,&ts,&cs,&tf,&cf);

    SSS=n+n+1;TTT=SSS+1;
    for(i=1;i<=n;++i)
    {
        e.insert(SSS,i,a[i],0),e.insert(i,SSS,0,0);
        e.insert(i+n,TTT,a[i],0),e.insert(TTT,i+n,0,0);
        e.insert(SSS,i+n,0x3f3f3f3f,newn),e.insert(i+n,SSS,0,-newn);
        if(i!=n)e.insert(i,i+1,0x3f3f3f3f,0),e.insert(i+1,i,0,0);
        if(i+tf<=n)e.insert(i,i+tf+n,0x3f3f3f3f,cf),e.insert(i+tf+n,i,0,-cf);
        if(i+ts<=n)e.insert(i,i+ts+n,0x3f3f3f3f,cs),e.insert(i+ts+n,i,0,-cs);
    }

    printf("%d\n",Dinic().second);

    return 0;
}
时间: 2024-12-15 22:46:47

[cogs461] [网络流24题#10] 餐巾 [网络流,最小费用最大流]的相关文章

LiberOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题

#6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 G 公司有 n nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n nn 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入格式 文件的第 1 11 行中有 1 11 个正整数 n nn,表示有 n nn 个仓库.第 2 22 行中有 n nn 个

Bashu2445 -- 【网络流24题-10】餐巾问题

2445 -- [网络流24题-10]餐巾问题 Description 一个餐厅在相继的n天里,每天需要用的餐巾数不尽相同.假设第i天需要ri块餐巾(i=1,2,…,n).餐厅可以购买新的餐巾,每块餐巾的费用为p分:也可以把旧餐巾送到快洗部,洗一块需m天,其费用为f分:也可以把旧餐巾送到慢洗部,洗一块需要t天(t>m),其费用为s < f分.每天结束时,餐厅必须决定多少块脏的餐巾送到快洗部.多少块送到慢洗部以及多少块保存起来延期送洗.但是洗好的餐巾和购买的新餐巾之和,要满足第i天的需求量,并使

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

[网络流24题]餐巾计划问题(最小费用最大流) 题面 COGS 洛谷上的数据范围更大,而且要开longlong 题解 餐巾的来源分为两种: ①新买的 ②旧的拿去洗 所以,两种情况分别建图 先考虑第一种 因为新买餐巾没有任何限制,并且随时可以买 所以直接从源点向每一天连边,容量为INF,费用为餐巾的价格 因为流要流出去,所以每个点向汇点连边,容量为每天的用量,费用为0 第二种,旧的拿去洗 首先考虑一下怎么算有多少旧的餐巾 每天用旧的餐巾的数量值一定的,不可能变多 因此从源点向这些点连边,容量为每天

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

#6008. 「网络流 24 题」餐巾计划 题目描述 一个餐厅在相继的 n nn 天里,每天需用的餐巾数不尽相同.假设第 i ii 天需要 ri r_ir?i?? 块餐巾.餐厅可以购买新的餐巾,每块餐巾的费用为 P PP 分:或者把旧餐巾送到快洗部,洗一块需 M MM天,其费用为 F FF 分:或者送到慢洗部,洗一块需 N NN 天,其费用为 S SS 分(S<F S < FS<F). 每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗.

【网络流24题】餐巾计划(图解)

LOJ 6008[网络流24题]餐巾计划 题解 一张图片说明建图方法: 解说: 这种建图方法完美区分开了"脏餐巾"和"干净餐巾"两种餐巾. 每天一定会有r[i]个脏餐巾,所以源点向每天的"脏餐巾"(图上used)连边,容量r[i],费用是0.另外,前一天的脏餐巾也可以留到下一天再处理,所以每天的used点向下一天的used点连一条边,容量INF,费用是0. 每天会需要r[i]个干净餐巾,所以每天的"干净餐巾"向汇点连边(图上n

【网络流24题】骑士共存问题(最大流)

[网络流24题]骑士共存问题(最大流) 题面 Cogs 题解 这题本质上和方格取数问题没有任何区别 首先也是可以黑白染色 因为马必定会跳到异色点上面去 然后同样的,源点向一种颜色,另一种颜色向汇点连边 因为代价就是1,所以容量都是1 这里考虑的"相邻"的情况是马的跳法 因此,枚举从当前点能够到达的位置,连一条容量为INF的边过去 障碍直接特殊考虑就行了 最后的答案就是所有可以放的位置数减去最大流(最小割) #include<iostream> #include<cst

CGOS461 [网络流24题] 餐巾(最小费用最大流)

题目这么说的: 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,…,N).餐厅可以从三种途径获得餐巾. 购买新的餐巾,每块需p分: 把用过的餐巾送到快洗部,洗一块需m天,费用需f分(f<p).如m=l时,第一天送到快洗部的餐巾第二天就可以使用了,送慢洗的情况也如此. 把餐巾送到慢洗部,洗一块需n天(n>m),费用需s分(s<f). 在每天结束时,餐厅必须决定多少块用过的餐巾送到快洗部,多少块送慢洗部.在每天开始时,餐厅必须决定是否购买新餐巾及多少,使洗好的和新购的餐巾之和满足当

「网络流24题」餐巾计划问题

题目描述 Description 一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同.假设第 i 天需要 ri块餐巾(i=1,2,…,N).餐厅可以购买新的餐巾,每块餐巾的费用为 p 分:或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分:或者送到慢洗部,洗一块需 n 天(n>m),其费用为 s<f 分.每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗.但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量.试设计一个算法为餐厅

【COGS 14】 [网络流24题] 搭配飞行员 网络流板子题

用网络流水二分图的模型(存一下板子) #include <cstdio> #include <cstring> #include <algorithm> #define N 105 #define R register #define inf 0x7f7f7f7f using namespace std; inline int read() { R int sum=0; R char ch=getchar(); while(ch<'0'||ch>'9')ch