• 寒假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<dist[v]) //如果不满足三角形不等式
    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 }

     有待学习:


    待解决:

    • 不明白为什么最小费用最大流中可以有负权边,但是不能有负权圈???
  • 相关阅读:
    JAVA实验3 类与对象
    多种排序功能的实现
    (数据结构)HashTable的实现
    对string型变量的频率统计(文章单词检索)
    对int型变量的频率统计
    二叉搜索树中序迭代器的实现
    二叉搜索树的实现
    Prim最小生成树
    Kruscal最小生成树
    算法分析实践大作业
  • 原文地址:https://www.cnblogs.com/OFSHK/p/12233599.html
Copyright © 2020-2023  润新知