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

题目这么说的:

一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,…,N)。餐厅可以从三种途径获得餐巾。

  1. 购买新的餐巾,每块需p分;
  2. 把用过的餐巾送到快洗部,洗一块需m天,费用需f分(f<p)。如m=l时,第一天送到快洗部的餐巾第二天就可以使用了,送慢洗的情况也如此。
  3. 把餐巾送到慢洗部,洗一块需n天(n>m),费用需s分(s<f)。

在每天结束时,餐厅必须决定多少块用过的餐巾送到快洗部,多少块送慢洗部。在每天开始时,餐厅必须决定是否购买新餐巾及多少,使洗好的和新购的餐巾之和满足当天的需求量Ri,并使N天总的费用最小。

挺有趣的题,至少还需要稍微思考思考。。考虑用最小费用最大流。

  • 首先显然要把各天作为点向汇点连容量为当天所需餐巾个数且费用为0的边,这样的最大流就满足各天供应的需求的条件;
  • 然后对于购买餐巾,源点向各天连容量为INF费用p的边;
  • 而最后还需要建洗餐巾重复利用餐巾的边,这么考虑:
    • 对于第i天都会有Ri个餐巾可以重复利用,而第j天(j>=i+m)则可以得到快洗的第i天的餐巾,单位费用为f,慢洗的同理;
    • 这样就清楚了:再新建n个顶点,源点向第i个新点连容量Ri费用0的边,第i个新点向第j天(j>=i+m)的点连容量INF费用f的边,第i个新点向第k天(k>=i+n)的点连容量INF费用s的边。

这样建完图跑最小费用最大流就OK了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 #define INF (1<<30)
 7 #define MAXN 444
 8 #define MAXM 444*888
 9 struct Edge{
10     int u,v,cap,cost,next;
11 }edge[MAXM];
12 int head[MAXN];
13 int NV,NE,vs,vt;
14
15 void addEdge(int u,int v,int cap,int cost){
16     edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost;
17     edge[NE].next=head[u]; head[u]=NE++;
18     edge[NE].u=v; edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost;
19     edge[NE].next=head[v]; head[v]=NE++;
20 }
21 bool vis[MAXN];
22 int d[MAXN],pre[MAXN];
23 bool SPFA(){
24     for(int i=0;i<NV;++i){
25         vis[i]=0;
26         d[i]=INF;
27     }
28     vis[vs]=1;
29     d[vs]=0;
30     queue<int> que;
31     que.push(vs);
32     while(!que.empty()){
33         int u=que.front(); que.pop();
34         for(int i=head[u]; i!=-1; i=edge[i].next){
35             int v=edge[i].v;
36             if(edge[i].cap && d[v]>d[u]+edge[i].cost){
37                 d[v]=d[u]+edge[i].cost;
38                 pre[v]=i;
39                 if(!vis[v]){
40                     vis[v]=1;
41                     que.push(v);
42                 }
43             }
44         }
45         vis[u]=0;
46     }
47     return d[vt]!=INF;
48 }
49 int MCMF(){
50     int res=0;
51     while(SPFA()){
52         int flow=INF,cost=0;
53         for(int u=vt; u!=vs; u=edge[pre[u]].u){
54             flow=min(flow,edge[pre[u]].cap);
55         }
56         for(int u=vt; u!=vs; u=edge[pre[u]].u){
57             edge[pre[u]].cap-=flow;
58             edge[pre[u]^1].cap+=flow;
59             cost+=flow*edge[pre[u]].cost;
60         }
61         res+=cost;
62     }
63     return res;
64 }
65 int need[222];
66 int main(){
67     freopen("napkin.in","r",stdin);
68     freopen("napkin.out","w",stdout);
69     int n,p,a,b,x,y;
70     scanf("%d",&n);
71     for(int i=1; i<=n; ++i){
72         scanf("%d",need+i);
73     }
74     scanf("%d%d%d%d%d",&p,&a,&b,&x,&y);
75     vs=0; vt=n*2+1; NV=vt+1; NE=0;
76     memset(head,-1,sizeof(head));
77     for(int i=1; i<=n; ++i){
78         addEdge(vs,i+n,INF,p);
79         addEdge(i+n,vt,need[i],0);
80         addEdge(vs,i,need[i],0);
81         for(int j=i+a; j<=n; ++j) addEdge(i,j+n,INF,b);
82         for(int j=i+x; j<=n; ++j) addEdge(i,j+n,INF,y);
83     }
84     printf("%d",MCMF());
85     return 0;
86 }
时间: 2024-10-11 01:23:35

CGOS461 [网络流24题] 餐巾(最小费用最大流)的相关文章

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

既然是最小费用最大流我们就用最大流来限制其一定能把每天跑满,那么把每个表示天的点向T连流量为其所需餐巾,费用为0的边,然后又与每天的餐巾对于买是无限制的因此从S向每个表示天的点连流量为INF,费用为一个餐巾的费用的边,然后我们考虑怎么用旧餐巾,我们用旧餐巾,要既不影响本点流量,也不影响本点费用,因此我们在开一坨点表示其对应得那天的旧餐巾,并通过他向离他快洗和离他慢洗天数的天的点连边,流量为Inf,费用为快洗.慢洗的费用,然后对于多余的旧餐巾,我们在一排天点中间从第一天连续地连到最后一天,流量为I

网络流(费用流):[网络流24题] 餐巾

[网络流24题] 餐巾 [问题描述] 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,…,N).餐厅可以从三种途径获得餐巾. (1)购买新的餐巾,每块需p分: (2)把用过的餐巾送到快洗部,洗一块需m天,费用需f分(f<p).如m=l时,第一天送到快洗部的餐巾第二天就可以使用了,送慢洗的情况也如此. (3)把餐巾送到慢洗部,洗一块需n天(n>m),费用需s分(s<f). 在每天结束时,餐厅必须决定多少块用过的餐巾送到快洗部,多少块送慢洗部.在每天开始时,餐厅必须决定是否购买新餐

LiberOJ #6002. 「网络流 24 题」最小路径覆盖

#6002. 「网络流 24 题」最小路径覆盖 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 给定有向图 G=(V,E) G = (V, E)G=(V,E).设 P PP 是 G GG 的一个简单路(顶点不相交)的集合.如果 V VV 中每个顶点恰好在 P PP 的一条路上,则称 P PP 是 G GG 的一个路径覆盖.P PP 中路径可以从 V VV 的任何一个顶点开始,

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

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

[网络流24题] 餐巾计划问题 [费用流]

题面: https://www.luogu.org/problemnew/show/P1251 思路: 这道题乍一看,可以跑上下界费用流 代码量.难度 -> inf 其实不然,我们可以用费用流的特殊处理去掉下界 观察题目,每天要求有ri块餐巾 首先,有贪心如下: 当且仅当每天可供使用的餐巾正好满足需求时,可以有最小费用 证明:若某一天有多一块餐巾,则其根本来源一定是买多了,而且在这块餐巾参与的周转中还消费了一些清洗费用,同时它造成其余的日子里也会有餐巾被闲置 因此首先把题目转化为"每天正好

网络流24题 餐巾计划问题

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

餐巾计划问题 【网络流24题】【费用流】【zkw】

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

网络流24题-运输问题(费用流)

题目描述 WW 公司有 mm 个仓库和 nn 个零售商店.第 ii 个仓库有 a_iai? 个单位的货物:第 jj 个零售商店需要 b_jbj? 个单位的货物. 货物供需平衡,即\sum\limits_{i=1}^{m}a_i=\sum\limits_{j=1}^{n}b_ji=1∑m?ai?=j=1∑n?bj?. 从第 ii 个仓库运送每单位货物到第 jj 个零售商店的费用为 c_{ij}cij??? . 试设计一个将仓库中所有货物运送到零售商店的运输方案,使总运输费用最少. 输入输出格式 输

BZOJ 1221 HNOI 2001 软件开发/网络流24题 餐巾计划问题 最小费用最大流

题目大意:有一个软件公司,每天需要给一些员工准备消毒毛巾,这些毛巾可以循环利用,但是需要消毒.可以将毛巾送去消毒,有两种方式,A天fA花费,B天fB花费.或者还可以直接买新毛巾,问为了满足员工的需求,至少需要花多少钱. 思路:经典的费用流问题.将每一天拆点,S向每一天<<1连边,约束每一天需要多少毛巾:每一天<<1|1向T连边,约束每一天需要的毛巾.每一天<<1向这一天清洗的毛巾能够使用的那一天<<1|1,注意A和B.毛巾可以延后使用,那么每一天<&l