2023.1.13

今日完成的[餐巾计划问题],是一道最小费用最大流的模板题,本人太弱在第一次使用dinic + spfa 完成此题时,也出现了许多问题,在此总结和提醒。

大致题意

一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同。假设第 i 天需要 \(r_i\)块餐巾( i=1,2,...,N)。餐厅可以购买新的餐巾,每块餐巾的费用为 p 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 n 天(n>m),其费用为 s 分(s<f)。

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

试设计一个算法为餐厅合理地安排好 N 天中餐巾使用计划,使总的花费最小。编程找出一个最佳餐巾使用计划。

思路整理

需要餐巾尽量多的情况下费用尽量少,考虑向网络流转化。考虑把每一天视为一个点即可以完成转移。脏餐巾可以向m/n天后转移,干净的餐巾会在使用的这一天转移为脏餐巾。

通过上文我们可以发现,对于每一天的餐巾,我们可以把它分为干净和脏,两个状态,所以一天就被拆成了两个点,转移如下:

​ 1.一天的脏餐巾流向n天后的干净餐巾,容量inf,边权p(n + i <= N)

​ 2.一天的脏餐巾流向m天后的干净餐巾,容量inf,边权s(m + i <= N)

​ 3.一天的脏餐巾流向明天的脏餐巾,容量inf,边权0(i + 1 <= N)

那么问题来了,我们怎么体现出“使用餐巾”、“购买餐巾”的过程呢?

时刻不要忘记网络流中源点和汇点的作用

​ 4.每一天源点流向脏餐巾,容量\(r_i\),边权0,干净餐巾流向汇点,容量\(r_i\),边权为0

​ 5.每一天源点流向干净餐巾,容量inf,边权p

原理:因为所跑是最大流,所以会尽量增多餐巾;而每天向汇点的流又是受限制的,就会刚好流\(r_i\)块餐巾;每次找的又是最短增广路,所以做法正确性得以证明,由于网络流算法时间较不稳定,理论时间复杂度是O($n ^ 2 $ m)

Code

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 5,inf = 0x7fffffff;
struct Edge{
int v,w,c,next;
}e[N * 2];
int n,d[N],vis[N],a[N],head[N],p,m,f,q,s,S,T,ans = 0,tot = 1;//1~n干净、n + 1~2n脏
inline void add(int x,int y,int c,int z)
{
++tot;
e[tot].v = y;
e[tot].w = z;
e[tot].c = c;
e[tot].next = head[x];
head[x] = tot;
}
inline bool spfa()
{
memset(vis,0,sizeof(vis));
for(int i=0;i<=T;i++) d[i] = inf / 2;
queue<int> q;
q.push(S);
vis[S] = 1;
d[S] = 0;
while(!q.empty())
{
int now = q.front();
q.pop();
vis[now] = 0;
for(int i = head[now];i;i = e[i].next)
{
int to = e[i].v;
if(e[i].c <= 0) continue;
if(d[to] > d[now] + e[i].w)
{
d[to] = d[now] + e[i].w;
if(!vis[to])
{
vis[to] = 1;
q.push(to);
}
}
}
}
if(d[T] < inf / 2)
return 1;
return 0;
}
inline int dinic(int x,int flow)
{
if(x == T) return flow;
int rest = flow;
vis[x] = 1;
for(int i = head[x];i && rest;i = e[i].next)
{
int to = e[i].v;
if(e[i].c <= 0 || d[to] != d[x] + e[i].w || vis[to]) continue;
int k = dinic(to,min(rest,e[i].c));
if(!k) d[to] = inf / 2;
e[i].c -= k;
rest -= k;
e[i ^ 1].c += k;
ans += k * e[i].w;
}
return flow - rest;
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cin>>p>>m>>f>>q>>s;
S = 0,T = 2 * n + 1;
for(int i=1;i<=n;i++)
{
add(S,i + n,a[i],0);
add(i + n,S,0,0);
add(i,T,a[i],0);
add(T,i,0,0);
add(S,i,a[i],p);
add(i,S,0,-p);
if(i + m <= n)
{
add(i + n,i + m,inf,f);
add(i + m,i + n,0,-f);
}
if(i + q <= n)
{
add(i + n,i + q,inf,s);
add(i + q,i + n,0,-s);
}
if(i + n + 1 <= n * 2)
{
add(i + n,i + n + 1,inf,0);
add(i + n + 1,i + n,0,0);
}
}
int flow = 0;
while(spfa())
{
memset(vis,0,sizeof(vis));
while(flow = dinic(S,inf / 2))
{
memset(vis,0,sizeof(vis));
flow = 0;
}
}
cout<<ans;
return 0;
}

2023.1.13 [网络流24题] 餐巾计划问题 LuoguP1251的更多相关文章

  1. 网络流24题 餐巾计划(DCOJ8008)

    题目描述 一个餐厅在相继的 n nn 天里,每天需用的餐巾数不尽相同.假设第 i ii 天需要 ri r_ir​i​​ 块餐巾.餐厅可以购买新的餐巾,每块餐巾的费用为 P PP 分:或者把旧餐巾送到快 ...

  2. 【zkw费用流】[网络流24题]餐巾计划问题

    题目描述 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,-,N).餐厅可以从三种途径获得餐巾. (1)购买新的餐巾,每块需p分: (2)把用过的餐巾送到快洗部,洗一块需m天,费用需f分(f ...

  3. 【Codevs1237&网络流24题餐巾计划】(费用流)

    题意:一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同. 假设第 i 天需要 ri块餐巾(i=1,2,…,N).餐厅可以购买新的餐巾,每块餐巾的费用为 p 分: 或者把旧餐巾送到快洗部,洗一块需 ...

  4. Cogs 461. [网络流24题] 餐巾(费用流)

    [网络流24题] 餐巾 ★★★ 输入文件:napkin.in 输出文件:napkin.out 简单对比 时间限制:5 s 内存限制:128 MB [问题描述] 一个餐厅在相继的N天里,第i天需要Ri块 ...

  5. [网络流24题]餐巾(cogs 461)

    [问题描述] 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,-,N).餐厅可以从三种途径获得餐巾. (1)购买新的餐巾,每块需p分: (2)把用过的餐巾送到快洗部,洗一块需m天,费用需f分 ...

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

    题目这么说的: 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,…,N).餐厅可以从三种途径获得餐巾. 购买新的餐巾,每块需p分: 把用过的餐巾送到快洗部,洗一块需m天,费用需f分(f< ...

  7. COGS461. [网络流24题] 餐巾

    [问题描述] 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,…,N).餐厅可以从三种途径获得餐巾. (1)购买新的餐巾,每块需p分: (2)把用过的餐巾送到快洗部,洗一块需m天,费用需f分 ...

  8. 【COGS 461】[网络流24题] 餐巾 最小费用最大流

    既然是最小费用最大流我们就用最大流来限制其一定能把每天跑满,那么把每个表示天的点向T连流量为其所需餐巾,费用为0的边,然后又与每天的餐巾对于买是无限制的因此从S向每个表示天的点连流量为INF,费用为一 ...

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

    #6008. 「网络流 24 题」餐巾计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  10. Libre 6008 「网络流 24 题」餐巾计划 (网络流,最小费用最大流)

    Libre 6008 「网络流 24 题」餐巾计划 (网络流,最小费用最大流) Description 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,-,N).餐厅可以从三种途径获得餐巾. ...

随机推荐

  1. 小程序利用canvas 绘制图案 (生成海报, 生成有特色的头像)

    小程序利用canvas 绘制图案 (生成海报, 生成有特色的头像) 微信小程序生成特色头像,海报等是比较常见的.下面我来介绍下实现该类小程序的过程. 首先选择前端来通过 canvas 绘制.这样比较节 ...

  2. 【深入浅出 Yarn 架构与实现】2-3 Yarn 基础库 - 服务库与事件库

    一个庞大的分布式系统,各个组件间是如何协调工作的?组件是如何解耦的?线程运行如何更高效,减少阻塞带来的低效问题?本节将对 Yarn 的服务库和事件库进行介绍,看看 Yarn 是如何解决这些问题的. 一 ...

  3. css文字垂直展示的方法

    一.使用writing-mode(推荐使用) writing-mode:翻译过来是"写字 - 模式",文本在水平或垂直方向上如何排布 有以下几个属性值: horizontal-tb ...

  4. natapp内网穿透

    NATAPP 官网地址 https://natapp.cn/ 下载 点击下载,选择符合自己的版本 注册 下载完成后解压是个natapp.exe程序,这里先不用动,回到官网首页 完成注册并登录,选择免费 ...

  5. JDK源码分析实战系列-PriorityQueue

    完全二叉树 一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下.从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树 ...

  6. VS使用web deploy发布到远程服务器

    如果是先安装 web deploy后安装iis的功能,需要在iis功能安装好后,修复下web deploy(直接运行web deploy的安装程序有修复)(本人也死在这里) 1.iis开启管理服务,和 ...

  7. 说一下 ArrayList 和 LinkedList 的区别?

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 前言 大家好,我是小彭. 在上一篇文章里,我们聊到了基于动态数组 ArrayList 线性表,今天我们来讨论 ...

  8. CPU体系(1):内存模型 & CPU Cache一致性 (待整理)

    C++中的 volatile, atomic, memory barrier 应用场景对比 -- volatile memory barrier atomic 抑制编译器重排 Yes Yes Yes ...

  9. MongoDB - 事务支持

    事务简介 事务是数据库中处理的逻辑单元,每个事务中包括一个或多个数据库操作,既可以是读操作,也可以是写操作. ACID 是一个"真正"事务所需要具备的一组属性集合,指的是原子性(A ...

  10. day11 枚举类enum & 单例模式 & 异常以及抛出

    day11 枚举enum 用enum关键字定义枚举类 特点 1.用enum关键字定义枚举类 2.枚举类默认继承java.lang.Enum类 3.枚举类的构造方法只能使用private修饰,省略则默认 ...