zoukankan      html  css  js  c++  java
  • 最小费用最大流

    一、问题描述

    最小费用最大流:  在最大流有多组解时,给每条边在附上一个单位费用的量,问在满足最大流时的最小费用是多少?

    二、算法描述

    思想:  给出一个容量网络,那他的最大流一定是一个定值(即使是有多个一样的最大值)。所以我们从开始的可行流开始增广时,最终的增广量是一定的。所以为了满足最小费用我们只需要每次找最小费用的增广路即可,直到流量为最大值。这个问题仅仅是在求增广路时先考虑费用最小的增广路,其他思想和EK思想一样。  

    我们学过SPFA求最短路算法(bellman-ford的队列优化),所以我们将弧的费用看做是路径长度,即可转化为求最短路的问题了。只需要所走的最短路满足两个条件即可:1可增广cap> flow,2路径变短d[v]>d[u]+cost< u,v> 。  

    关于建图的方式和Dinic,ISAP算法一样,如有疑问可以去我们其他相关博客看看。

    模板:

    //最小费用最大流,求最大费用只需要取相反数,结果取相反数即可。 
    //点的总数为 N,点的编号 0~N-1 
    const int MAXN = 10000; 
    const int MAXM = 100000; 
    const int INF = 0x3f3f3f3f; 
    struct Edge 
    { 
        int to,next,cap,flow,cost; 
    }edge[MAXM]; 
    int head[MAXN],tol; 
    int pre[MAXN],dis[MAXN]; 
    bool vis[MAXN]; 
    int N;//节点总个数,节点编号从0~N-1 
    void init(int n) 
    { 
        N = n; 
        tol = 0; 
        memset(head,-1,sizeof(head)); 
    } 
    void addedge(int u,int v,int cap,int cost) 
    { 
        edge[tol].to = v; 
        edge[tol].cap = cap; 
        edge[tol].cost = cost; 
        edge[tol].flow = 0; 
        edge[tol].next = head[u]; 
        head[u] = tol++; 
        edge[tol].to = u; 
        edge[tol].cap = 0; 
        edge[tol].cost = -cost; 
        edge[tol].flow = 0; 
        edge[tol].next = head[v]; 
        head[v] = tol++; 
    } 
    bool spfa(int s,int t) 
    { 
        queue<int>q; 
        for(int i = 0;i < N;i++) 
        { 
            dis[i] = INF; 
            vis[i] = false; 
            pre[i] = -1; 
        } 
        dis[s] = 0; 
        vis[s] = true; 
        q.push(s); 
        while(!q.empty()) 
        { 
            int u = q.front(); 
            q.pop(); 
            vis[u] = false; 
            for(int i = head[u]; i != -1;i = edge[i].next) 
            { 
                int v = edge[i].to; 
                if(edge[i].cap > edge[i].flow && 
                   dis[v] > dis[u] + edge[i].cost ) 
                { 
                    dis[v] = dis[u] + edge[i].cost; 
                    pre[v] = i; 
                    if(!vis[v]) 
                    { 
                        vis[v] = true; 
                        q.push(v); 
                    } 
                } 
            } 
        } 
        if(pre[t] == -1)return false; 
        else return true; 
    } 
    //返回的是最大流,cost存的是最小费用 
    int minCostMaxflow(int s,int t,int &cost) 
    { 
        int flow = 0; 
        cost = 0; 
        while(spfa(s,t)) 
        { 
            int Min = INF; 
            for(int i = pre[t];i != -1;i = pre[edge[i^1].to]) 
            { 
                if(Min > edge[i].cap - edge[i].flow) 
                    Min = edge[i].cap - edge[i].flow; 
            } 
            for(int i = pre[t];i != -1;i = pre[edge[i^1].to]) 
            { 
                edge[i].flow += Min; 
                edge[i^1].flow -= Min; 
                cost += edge[i].cost * Min; 
            } 
            flow += Min; 
        } 
        return flow; 
    } 
    

      

  • 相关阅读:
    SmartTimer——一种基于STM32的轻量级时钟调度器
    Python2/3中的urllib库
    Python 解析构建数据大杂烩 -- csv、xml、json、excel
    Python2/3 中执行外部命令(Linux)和程序(exe) -- 子进程模块 subprocess
    Python 中的命令行参数处理 -- argparse、optparse、getopt
    Linux 定时循环执行 python 脚本
    Python2/3的中、英文字符编码与解码输出: UnicodeDecodeError: 'ascii' codec can't decode/encode
    在windows下使用Qt5开发GTK3图形界面应用程序
    qt编译的基于xlib cairo的桌面程序
    debian安装dwm窗口管理器
  • 原文地址:https://www.cnblogs.com/xzxl/p/7236170.html
Copyright © 2011-2022 走看看