P1251 餐巾计划问题 (费用流)

题目链接

方法:

重点在建图!!!将一天拆成晚上和早上;

1. 从源点向每一天晚上连一条流量为当天所用餐巾x,费用为0的边;

2. 每一天早上向汇点连一条流量为当天所用餐巾x,费用为0的边;

3. 从每一天晚上向第二天晚上连一条流量为INF,费用为0的边,表示每天晚上可以将脏餐巾留到第二天晚上;

4. 从每一天晚上向这一天+快洗所用天数t1的那一天早上连一条流量为INF,费用为快洗所用钱数的边,表示每天晚上可以送去快洗部,在地i+t1天早上收到餐巾 ;

5. 从每一天晚上向这一天+慢洗所用天数t2的那一天早上连一条流量为INF,费用为慢洗所用钱数的边,表示每天晚上可以送去慢洗部,在地i+t2天早上收到餐巾;

6. 从起点向每一天早上连一条流量为INF,费用为购买餐巾所用钱数的边,表示每天早上可以购买餐巾 。

Code:

  1 #include <bits/stdc++.h>
  2 #define LL long long
  3 using namespace std;
  4
  5 const int maxn=2000;
  6 const int INF=0x7fffffff;
  7 int N;
  8 int S,T;
  9 struct Edge{
 10     int next, from, to, remain,fi;
 11 }e[100000];
 12 int head[10000];
 13 int en;
 14 LL dis[10000];
 15 int preEdge[10000];
 16 queue<int> q;
 17 int inqueue[10000];
 18 LL res;
 19 int minflow[10000];
 20
 21 void addEdge(int from, int to, int flow, int fi){
 22     e[en].next=head[from];
 23     e[en].from=from;
 24     e[en].to=to;
 25     e[en].remain=flow;
 26     e[en].fi=fi;
 27     head[from]=en;
 28     ++en;
 29 }
 30
 31 void add(int from, int to, int flow, int fi){
 32     addEdge(from,to,flow,fi);
 33     addEdge(to,from,0,-fi);
 34 }
 35
 36 void spfa(){
 37     memset(minflow,0,sizeof(minflow));
 38     memset(dis,127,sizeof(dis));
 39     memset(preEdge,-1,sizeof(preEdge));
 40     dis[S]=0;
 41     minflow[S]=INF;
 42     q.push(S);
 43     inqueue[S]=1;
 44     while(!q.empty()){
 45         int u=q.front();
 46         q.pop();
 47         inqueue[u]=0;
 48         for(int i=head[u];i!=-1;i=e[i].next){
 49             int v=e[i].to;
 50             int c=e[i].fi;
 51             if(e[i].remain>0 && dis[u]+c<dis[v]){
 52                 dis[v]=dis[u]+c;
 53                 preEdge[v]=i;
 54                 minflow[v]=min(minflow[u],e[i].remain);
 55                 if(!inqueue[v]){
 56                     q.push(v);
 57                     inqueue[v]=1;
 58                 }
 59             }
 60         }
 61     }
 62 }
 63
 64 void EK(){
 65
 66     while(true){
 67         spfa();
 68         if(preEdge[T]==-1) break;
 69         int v=T;
 70         while(true){
 71             int edge=preEdge[v];
 72             if(edge==-1) break;
 73             e[edge].remain-=minflow[T];
 74             e[edge^1].remain+=minflow[T];
 75             v=e[edge].from;
 76         }
 77         res+=dis[T]*minflow[T];
 78     }
 79 }
 80
 81 int main(){
 82     memset(head,-1,sizeof(head));
 83     scanf("%d", &N);
 84     S=0;
 85     T=2*N+1;
 86     for(int i=1;i<=N;++i){
 87         int c;
 88         scanf("%d", &c);
 89         add(i,T,c,0);
 90         add(S,i+N,c,0);
 91     }
 92     int p, m, f, n, s;
 93     scanf("%d %d %d %d %d", &p, &m, &f, &n, &s);
 94     for(int i=1;i<=N;++i){
 95         add(S,i,INF,p);
 96         if(i+1<=N){
 97             add(i+N,i+1+N,INF,0);
 98         }
 99         if(i+m<=N){
100             add(i+N,i+m,INF,f);
101         }
102         if(i+n<=N){
103             add(i+N,i+n,INF,s);
104         }
105     }
106     EK();
107     printf("%lld",res);
108     return 0;
109 }

原文地址:https://www.cnblogs.com/FEIIEF/p/12244588.html

时间: 2024-11-09 05:56:10

P1251 餐巾计划问题 (费用流)的相关文章

餐巾计划问题(费用流)

拆点,建二分图,Xi表示第i天用完的餐巾,Yi表示第i天需要的餐巾,求费用流. //http://www.cnblogs.com/IMGavin/ #include <iostream> #include <stdio.h> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <map> #include <

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

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

P1251 餐巾计划问题

\(\color{#0066ff}{题目描述}\) 一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同.假设第 i 天需要 \(r_i\) 块餐巾( i=1,2,...,N).餐厅可以购买新的餐巾,每块餐巾的费用为 p 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 n 天(\(n>m\)),其费用为 s 分(\(s<f\)). 每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗.但是每天洗好的餐巾和

HDU 6118 2017百度之星初赛B 度度熊的交易计划(费用流)

度度熊的交易计划 Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 254    Accepted Submission(s): 80 Problem Description 度度熊参与了喵哈哈村的商业大会,但是这次商业大会遇到了一个难题: 喵哈哈村以及周围的村庄可以看做是一共由n个片区,m条公路组成的地区. 由于生产能力的区别,第i个片

hdu 6118 度度熊的交易计划(可行费用流)

题目链接:hdu 6118 度度熊的交易计划 题意: 中文,说的很清楚了. 题解: 对着输入建一些图,跑一下可行费用流就行了,即当费用为正的时候就不跑了,这样就先满足了费用最小. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 5 namespace MCMF 6 { 7 const int N=1e5+7,inf=1e9+7; 8 int u[

P1251 餐巾计划 (网络流)

题意:餐厅每天会需要用Ri块新的餐巾 用完后也会产生Ri块旧的餐巾 每天购买新的餐巾单价p元 每天产出的旧餐巾可以送到快洗部花费每张c1元 在i + v1天可以使用 也可以花费c2元每张送到慢洗部 在i + v2天可以使用 问n天的最小花费 题解:把每天拆点 分为用出去的 和得到的旧餐巾 s -> 用出去的  表示每天可以买新的 用出去的-> t 表示每天一定会用Ri张纸巾 s-> 旧 表示每天一定会产生Ri块旧的纸巾 特判一下后 旧的按题意可以送去快洗和慢洗 然后今天没用完的旧的 明天

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

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

餐巾计划问题 zwk费用流解法

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

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

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