网络流二十四题之餐巾计划问题

  题目传送门

  这题的思路我觉得five20巨佬讲的已经非常清晰了,所以就推荐一下他的题解,我就只放代码了

//It is made by HolseLee on 7th Feb 2018
//Luogu.org P1251
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
#define inf 1e12
const int N=20001;
typedef long long ll;
ll n,d1,d2,c1,c2,p;
ll sta,endd,head[N];
ll cnt=1,ans,dis[N];
bool vis[N],inq[N];
struct Node{
  ll to,val;
  ll cost,next;
}edge[N<<2];
queue<ll>team;
inline ll read()
{
  char ch=getchar();ll num=0;bool flag=false;
  while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)flag=true;ch=getchar();}
  while(ch>=‘0‘&&ch<=‘9‘){num=num*10+ch-‘0‘;ch=getchar();}
  return flag?-num:num;
}
inline void add(ll x,ll y,ll z,ll c)
{
  edge[++cnt].to=y;
  edge[cnt].val=z;
  edge[cnt].cost=c;
  edge[cnt].next=head[x];
  head[x]=cnt;
}
inline void add_edge(ll x,ll y,ll z,ll c)
{add(x,y,z,c);add(y,x,0,-c);}
inline bool spfa()
{
  for(ll i=sta;i<=endd;i++)dis[i]=inf;
  memset(inq,false,sizeof(inq));
  team.push(endd);dis[endd]=0;
  inq[endd]=true;
  while(!team.empty()){
    ll u=team.front();team.pop();
    inq[u]=false;
    for(ll i=head[u];i!=-1;i=edge[i].next){
      ll v=edge[i].to;
      if(edge[i^1].val&&dis[v]>dis[u]-edge[i].cost){
    dis[v]=dis[u]-edge[i].cost;
    if(!inq[v]){
      inq[v]=true;
      team.push(v);
    }
      }
    }
  }
  return dis[sta]<inf;
}
inline ll dfs(ll u,ll nowflow)
{
  vis[u]=true;
  if(nowflow==0||u==endd)return nowflow;
  ll used=0;
  for(ll i=head[u];i!=-1;i=edge[i].next){
    ll v=edge[i].to;
    if(!vis[v]&&edge[i].val&&dis[v]==dis[u]-edge[i].cost){
      ll ka=dfs(v,min(nowflow,edge[i].val));
      edge[i].val-=ka;edge[i^1].val+=ka;
      used+=ka;nowflow-=ka;
      if(nowflow==0)return used;
    }
  }
  return used;
}
void ready()
{
  memset(head,-1,sizeof(head));
  n=read();ll x;
  sta=0;endd=2*n+1;
  for(ll i=1;i<=n;i++){
    x=read();
    add_edge(sta,i+n,x,0);
    add_edge(i,endd,x,0);}
  p=read();
  d1=read();c1=read();
  d2=read();c2=read();
  for(ll i=1;i<=n;i++){
    add_edge(sta,i,inf,p);
    if(i+d1<=n)add_edge(i+n,i+d1,inf,c1);
    if(i+d2<=n)add_edge(i+n,i+d2,inf,c2);
    if(i+1<=n)add_edge(i,i+1,inf,0);
  }
}
void work()
{
  while(spfa()){
    vis[endd]=true;
    while(vis[endd]){
      memset(vis,false,sizeof(vis));
      ll ka=dfs(sta,inf);
      ans+=ka*dis[sta];
    }
  }
  printf("%lld",ans);
}
int main()
{
  ready();
  work();
  return 0;
}

原文地址:https://www.cnblogs.com/cytus/p/8427437.html

时间: 2024-10-03 09:35:24

网络流二十四题之餐巾计划问题的相关文章

网络流二十四题

网络流二十四题 网络流是个好东西,希望我也会. 网络流?\(orz\ zsy!!!!!\) P2766 最长不下降子序列问题 考虑我们是如何\(dp\)这个\(LIS\)的. 我们是倒着推,设置\(dp(i)\)代表以\(i\)为起点的\(LIS\)是多少.转移太显然了 \[ dp(i)=max\{dp(j)\}+1,data[i]\le data[j] \] 想一想一个合法的\(LIS\)方案代表着什么,代表着它是由这个式子一个一个推出来的. 考虑一个数字只能用一次,那么我们直接拆成两个点\(

网络流二十四题之魔术球问题

P2765 魔术球问题 题目描述 «问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.例如,在4 根柱子上最多可放11 个球. «编程任务: 对于给定的n,计算在n根柱子上最多能放多少个球. 输入输出格式 输入格式: 第1 行有1个正整数n,表示柱子数. 输出格式: 程序运行结束时,将n 根柱子上最

网络流二十四题 分配问题

分配问题 题目描述 有 nn 件工作要分配给 nn 个人做.第 ii 个人做第 jj 件工作产生的效益为 c_{ij}cij? .试设计一个将 nn 件工作分配给 nn 个人做的分配方案,使产生的总效益最大. 输入输出格式 输入格式: 文件的第 11 行有 11 个正整数 nn ,表示有 nn 件工作要分配给 nn 个人做. 接下来的 nn 行中,每行有 nn 个整数 c_{ij}cij? ??,表示第 ii 个人做第 jj 件工作产生的效益为 c_{ij}cij? . 输出格式: 两行分别输出

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

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

【网络流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). 每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗.

微软云计算介绍与实践(实践之二十四)

测试Runbook 小张现在已经创造了他的第一个Runbook.他现在所要做的唯一事情是启动Runbook,同时提供四个参数让他的工作实现自动化,节省他的时间.但他实际运行之前,他必须检查看看Runbook是否可用.为此,他将使用被集成到Orchestrator中的Runbook测试仪,对于这次测试,小张创建一个名为"XYZ"的云,并配置以下资源: 内存:16GB        存储:200GB       允许在云中建立最多8个虚拟机 1.在菜单栏中选择Runbook测试仪 2.Sy

三十四、Linux系统任务计划cron、chkconfig工具、systemd管理服务、unit介绍

三十四.Linux系统任务计划cron.chkconfig工具.systemd管理服务.unit介绍.target介绍 一.Linux系统任务计划cron crontab命令:对任务计划功能的操作用此命令.选项: -u:指定某个用户,不加-u则为当前用户. -e:制定任务计划. -l:列出任务计划. -r:删除任务计划. 任务计划的配置文件:/etc/crontab 文件内共有五个字段. 从左往右依次为:分.时.日.月.周.用户.命令. 可以不指定用户就是root. # crontab -e  

从零开始学android&lt;android事件的处理方式.二十四.&gt;

在android中一共有 多种事件,每种事件都有自己相对应的处理机制 如以下几种 1 单击事件 View.OnClickListener public abstract void onClick (View v) 单击组件时触发 2 单击事件 View.OnLongClickListener public abstract boolean onLongClick (View v) 长按组件时触发 3 键盘事件 View.OnKeyListener public abstract boolean