今天学习了最小费用最大流,是网络流算法之一。可以对于一个每条边有一个容量和一个费用(即每单位流的消耗)的图指定一个源点和汇点,求在从源点到汇点的流量最大的前提下的最小费用。

  这里讲一种最基础也是最好掌握的实现算法,就是spfa求费用流。

  其实也很简单,在最大流的基础上,我们将dfs增广替换成对于费用为权值的边跑spfa得到的最短路,相当于一个贪心的思想。证明有一定难度,稍微口糊一下,就像ford-fulkerson一样,这个算法每次都能找到一条单位流费用和最小的路径,又由于路径中每条边的流量相等,每次增广就能使得单位流量的平均费用更小,而最大流流量是不变的,这样就能使得费用最小。

  网络流算法主要考建图,所以模板只要会默下来就够了,还有就是:

  一定要会写spfa!!!

  对于spfa,这里有两个小优化。

  一个是slf优化,就是对于spfa的进队操作,进之前判一下若小于队头就直接插在队头,这个还是蛮有用的,可以提升点速度;

  另一个是记路径的时候可以不用记前趋点,只要记边,反向边指向的就是前趋,就不用多开一个数组的空间。(这个是zxyer学长当时说的)

  下面贴上代码:

  这是网络流24题中的餐巾计划问题。

  题目大意是:一个饭馆每天需要使用ri条干净的餐巾,用完就脏了,干净餐巾可以由3种方式得到:

    1.直接购买,p元一条;

    2.快洗,需要t1天,花费w1元;

    3.慢洗,需要t2天,花费w2元;

  所以我们建6种边,把每天拆成两个点,分别为干净的(1~n)和脏的(n+1~n*2),这里要注意的是,干净的不直接向脏的连边,而是连向T,相当于必须送满ri条给顾客使用,再从S送到脏的一边。

  1. #include<cstdio>
  2. using namespace std;
  3. const int inf=;
  4. int n,m,p,t1,w1,t2,w2,tot=,mx,q[],d[],pree[],h[];
  5. struct edge{int to,nxt,cst,cap;}e[];
  6. bool vis[];
  7. int mn(int x,int y){return x>y?y:x;}
  8. void add(int fr,int to,int cst,int cap)
  9. {
  10. e[++tot]={to,h[fr],cst,cap};h[fr]=tot;
  11. e[++tot]={fr,h[to],-cst,};h[to]=tot;//建一条容量为0费用为-cap的反向边且满足正反边异或值为1方便将边取反
  12. }
  13. void init()
  14. {
  15. scanf("%d%d%d%d%d%d",&n,&p,&t1,&w1,&t2,&w2);
  16. for(int i=;i<=n;i++)
  17. {
  18. int r;scanf("%d",&r);mx+=r;
  19. add(,n+i,p,inf);//直接购买花费p元
  20. add(,i,,r);//当天用完的旧餐巾
  21. add(i+n,n*+,,r);//当天需要使用的新餐巾
  22. if(i+t1<=n)add(i,i+n+t1,w1,inf);//快洗花费t1时间,每条w1元
  23. if(i+t2<=n)add(i,i+n+t2,w2,inf);//快洗花费t2时间,每条w2元
  24. if(i<n)add(i,i+,,inf);//不需要做任何事的餐巾积到明天(也可以先洗完然后放在那边等就是n+i连向n+i+1)
  25. }
  26. n=n*+;
  27. }
  28. bool spfa()
  29. {
  30. for(int i=;i<=n;i++)d[i]=inf;
  31. int l=,r=;q[]=;vis[]=;
  32. while(l!=r)
  33. {
  34. int x=q[l=l==n?:l+];
  35. for(int i=h[x];i;i=e[i].nxt)
  36. if(e[i].cap&&e[i].cst+d[x]<d[e[i].to])
  37. {
  38. int v=e[i].to;
  39. pree[v]=i;
  40. d[v]=d[x]+e[i].cst;
  41. if(!vis[v])
  42. {
  43. if(d[v]>d[l+])q[r=r==n?:r+]=v;
  44. else q[l]=v,l=l==?n:l-;//这边加的是slf优化,用了循环队列来写
  45. vis[v]=;
  46. }
  47. }
  48. vis[x]=;
  49. }
  50. return d[n]==inf?:;
  51. }
  52. int costflow()
  53. {
  54. int cost=,mm=;
  55. while(spfa())
  56. {
  57. int mi=inf;
  58. for(int i=n;i;i=e[pree[i]^].to)//记路径时记下前趋路径
  59. mi=mn(mi,e[pree[i]].cap);
  60. for(int i=n;i;i=e[pree[i]^].to)
  61. {
  62. int ee=pree[i];
  63. e[ee].cap-=mi;
  64. e[ee^].cap+=mi;
  65. }
  66. cost+=d[n]*mi;
  67. mm+=mi;
  68. }
  69. return mm==mx?cost:;//是否满流的判断(这道题不会出现不满流的情况,所以不加也可)
  70. }
  71. int main()
  72. {
  73. init();
  74. printf("%d",costflow());
  75. return ;
  76. }

初识费用流 模板(spfa+slf优化) 餐巾计划问题的更多相关文章

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

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

  2. 【费用流】【Next Array】费用流模板(spfa版)

    #include<cstdio> #include<algorithm> #include<cstring> #include<queue> using ...

  3. HDU 6611 K Subsequence(Dijkstra优化费用流 模板)题解

    题意: 有\(n\)个数\(a_1\cdots a_n\),现要你给出\(k\)个不相交的非降子序列,使得和最大. 思路: 费用流建图,每个点拆点,费用为\(-a[i]\),然后和源点连边,和后面非降 ...

  4. [BZOJ 2200][Usaco2011 Jan]道路和航线 spfa+SLF优化

    Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...

  5. HDU2686 费用流 模板

    Matrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  6. spfa + slf优化

    最近在练习费用流 , 不是要用spfa吗 ,我们教练说:ns学生写朴素的spfa说出去都让人笑 . QwQ,所以就去学了一下优化 . slf优化就是双向队列优化一下,本来想用lll优化,可是优化后我t ...

  7. hdu1533 费用流模板

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  8. POJ - 3268 Silver Cow Party SPFA+SLF优化 单源起点终点最短路

    Silver Cow Party One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to ...

  9. 费用流模板(带权二分图匹配)——hdu1533

    /* 带权二分图匹配 用费用流求,增加源点s 和 汇点t */ #include<bits/stdc++.h> using namespace std; #define maxn 1000 ...

随机推荐

  1. 面试:谈谈你对jQuery的理解

    jQuery是一个轻量级的javascript框架,极大的简化了js的编程. 1.首先jQuery提供了强大的元素选择器.用于获取html页面中封装了html元素的jQuery对象.像常见的选择器有: ...

  2. asp.net异步上传

    界面如下:

  3. MATLAB中的randi函数

    randi Pseudorandom integers from a uniform discrete distribution.来自一个均匀离散分布的伪随机整数 R = randi(IMAX,N) ...

  4. iOS进阶--将项目的编译速度提高5倍

    前言 作为开发团队的负责人,最近因为在快速迭代开发新功能,项目规模急速增长,单个端业务代码约23万行,私有库约6万行,第三方库代码约15万行,单个客户端的代码行数约60万.现在打包一次耗时需要11~1 ...

  5. BZOJ 2208 连通数(强连通分量)

    先缩点,对于缩完点后的DAG,可以直接在每个scc dfs一次就可以求出终点是这个scc的点的点对个数. # include <cstdio> # include <cstring& ...

  6. [WC2005]双面棋盘

    description 洛谷 给出一个\(n\times n\)的黑白棋盘. \(m\)次操作,每次将一个格子进行颜色翻转,求每次操作后的黑白四连通块数. data range \[n\le 200, ...

  7. CodeForces 185A. Plant (矩阵快速幂)

    CodeForces 185A. Plant (矩阵快速幂) 题意分析 求解N年后,向上的三角形和向下的三角形的个数分别是多少.如图所示: N=0时只有一个向上的三角形,N=1时有3个向上的三角形,1 ...

  8. URAL.1033 Labyrinth (DFS)

    URAL.1033 Labyrinth (DFS) 题意分析 WA了好几发,其实是个简单地DFS.意外发现这个俄国OJ,然后发现ACRUSH把这个OJ刷穿了. 代码总览 #include <io ...

  9. MyBatis代码生成工具mybatis-generator在Myeclipse10中的使用

    一.在MyEclipse安装目录下新建myPlugin目录,如下图所示: 二.将 mybatis.zip 里面的文件放在MyEclipse的dropins目录下,如下图所示: 三.在Myeclipse ...

  10. 8VC Venture Cup 2016 - Final Round (Div. 2 Edition) A

    A. Orchestra time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...