寒假Day12:最小费用最大流问题入门

最小费用最大流相关概念

费用流即在网络流的基础上,给每条边都加了费用(费用有正有负)。

增广路:它的最大流量取决于增广路上流量最小的边。短板效应,最大容量取决于最短木板。   

求解费用流的思想:

  • 在总流量最大的前提下求解总费用最小的流,即最小费用最大流。
  • 通过SPFA算法进行增广,每一次增广之后都可以得出一个费用,所用费用相加即是最小费用。(因为SPFA是最短路算法,最短路使得每次增广的流的费用最小,所以所得即最小答案)

注意:如果存在两条边,但是费用不同的话无法合并。

   可以有负权边,但是不能有负权圈。

求解算法:MCMF算法(即SPFA+EK)。SPFA用来计算最小费用路径,即增广路)

 


 

 

最小费用最大流的变形:

  1. 最大费用最小流:在添边的时候交换位置即可;
  2. 最大费用最大流:在添边的时候把取边的费用的相反数,用最小费用最大流求解后对于答案取反,即可得到最大费用(权值)。见之后的博客POJ3680

 


 

引入SPFA

先复习一下SPFA(因为图中可能会出现负的费用,所以不能用Dijkstra。)

(但是,在没有负环、单纯求最短路径的情况下,不建议使用SPFA,而是用Dijkstra。)

SPFA时间复杂度分析:

如果图是随机生成的,时间复杂度为 O(KM)(K可以认为是个常数,m为边数,n为点数);

但是实际上SPFA的算法复杂度是 O(N*M),但是出题人可以构造出卡SPFA的数据,让SPFA超时。

https://www.luogu.com.cn/blog/83547/spfa-suan-fa-jiao-xue  可以看一下这一篇,用静态邻接表(也就是链式前向星)实现。

 

我的SPFA模板:

 1 void spfa(int x)
 2 {
 3     for(int i=1; i<=N; i++)
 4     {
 5         dist[i]=inf;
 6         book[i]=0;
 7     }
 8     dist[x]=0;//源点到自身距离为0
 9     queue<int>Q;
10     q.push(s);//源点入队
11     book[x]=1;
12     while(!Q.empty())
13     {
14         int u=Q.front();
15         Q.pop();
16         book[u]=0;
17         for(int i=head[u]; i!=-1; i=edge[i].next)
18         {
19             int v=edge[i].to;
20             if(dist[u]+edge[i].w//如果不满足三角形不等式
21             {
22                 dist[v]=dist[u]+edge[i].w;//更新答案
23                 if(book[v]==0) //如果不在队列
24                 {
25                     Q.push(v);//则入队
26                     book[v]=1;//进行标记
27                 }
28             }
29         }
30     }
31 }

 

 


 

 有待学习:

寒假Day12:最小费用最大流问题入门_第1张图片

 


 

待解决:

  • 不明白为什么最小费用最大流中可以有负权边,但是不能有负权圈???

你可能感兴趣的:(寒假Day12:最小费用最大流问题入门)