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. java学习之spirng的aop

    AOP技术 0x00前言 什么是AOP技术:在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的 ...

  2. mysql删库报错

    3.开发人员测试环境删库报错 #解决:在数据库的物理目录中(mysql的data目录),进入要删除的数据库目录,查看是否有文件存在,若存在,使用rm -rf 命令清除:再次执行删除数据库命令即可 [r ...

  3. 基于python的数学建模---机场航线设计

    数据集 拿走: 链接:https://pan.baidu.com/s/1zH5xhpEmx2_u5qO9W4gCkw 提取码:2wl5 数据集来自航空业,有一些关于航线的基本信息.有某段旅程的起始点和 ...

  4. Android网络请求(终) 网络请求框架Retrofit

    Android网络请求(终) 网络请求框架Retrofit Retrofit底层是由OkHttp封装的,Retrofit对于注解的使用十分频繁,所以不了解注解的同学们可以去查查资料什么的. 这里有一个 ...

  5. python-CSV文件的读写

    CSV文件:Comma-Separated Values,中文叫逗号分隔值或者字符分隔值,其文件以纯文本的形式存储表格数据. 可以理解成一个表格,只不过这个 表格是以纯文本的形式显示,单元格与单元格之 ...

  6. Tkinter根据屏幕分辨率最大化适应屏幕

    还不能够实现所有组件随分辨率自动变化 # 实现的是界面覆盖整个屏幕 from tkinter import * import win32api, win32con # 获取屏幕的分辨率 width = ...

  7. 第2-4-10章 规则引擎Drools实战(3)-保险产品准入规则

    目录 9.3 保险产品准入规则 9.3.1 决策表 9.3.2 规则介绍 9.3.3 实现步骤 9.3 保险产品准入规则 全套代码及资料全部完整提供,点此处下载 9.3.1 决策表 前面我们编写的规则 ...

  8. 【RocketMQ】主从同步实现原理

    主从同步的实现逻辑主要在HAService中,在DefaultMessageStore的构造函数中,对HAService进行了实例化,并在start方法中,启动了HAService: public c ...

  9. Java单例模式的最佳实践?

    "读过书,--我便考你一考.茴香豆的茴字,怎样写的?"--鲁迅<孔乙己> 0x00 大纲 目录 0x00 大纲 0x01 前言 0x02 单例的正确性 new关键字 c ...

  10. PowerDotNet平台化软件架构设计与实现系列(14):平台建设指南

    软件开发中常见的几种不同服务模型包括SaaS(软件即服务).LaaS(许可即服务).PaaS(平台即服务).CaaS(容器即服务).IaaS(基础设施即服务)和FaaS(功能即服务). 很多人认为Ia ...