zoukankan      html  css  js  c++  java
  • 【模板】最小费用最大流

    给出一个容量网络,那他的最大流一定是一个定值(即使是有多个一样的最大值)。
    所以我们从开始的可行流开始增广时,最终的增广量是一定的。
    所以为了满足最小费用我们只需要每次找最小费用的增广路即可,直到流量为最大值。
    这个问题仅仅是在求增广路时先考虑费用最小的增广路,其他思想和EK思想一样。
    我们学过SPFA求最短路算法(bellman-ford的队列优化),所以我们将弧的费用看做是路径长度,即可转化为求最短路的问题了。只需要所走的最短路满足两个条件即可:1剩余流量不为0,2路径变短d[v]>d[u]+cost< u,v> 。

    https://www.luogu.org/problem/show?pid=3381#sub
    这里写图片描述

    #include<iostream>
    #include<cstring>
    #include<string>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    int n,m,S,T;
    int num[100005],cap[100005],cost[100005],nxt[100005],head[5005],cnt=1;//cap记残余流量,cost记费用
    int dis[5005],flow[5005],xb[5005];//xb记链表数组的下标,dis用于spfa
    int pre[5005];
    bool used[5005];
    int mflow=0,mcost=0;
    void add(int from,int to,int ca,int co)
    {
        cnt++;//从 2 开始 ,若从0开始,会导致找点时循环停止!!!
        num[cnt]=to;
        nxt[cnt]=head[from];
        head[from]=cnt;
        cost[cnt]=co;
        cap[cnt]=ca;
    }
    int bfs(int s,int t)
    {
        memset(dis,127,sizeof(dis));
        memset(used,false,sizeof(used));
        for(int i=1;i<=n;i++) pre[i]=-1;
        queue <int> q;
        while(!q.empty()) q.pop();
    
        q.push(s);
        pre[s]=0;
        dis[s]=0; 
        used[s]=true;
        flow[s]=dis[0];
    
        while(!q.empty())
        {
            int k=q.front();
            q.pop();
            used[k]=false;
    
            for(int i=head[k];i;i=nxt[i])
            {
                int to=num[i];
                if(cap[i]>0&&dis[to]>dis[k]+cost[i])//在spfa判断条件基础上,加上剩余流量>0
                {
                    xb[to]=i;
                    dis[to]=dis[k]+cost[i];
                    flow[to]=min(flow[k],cap[i]);
                    if(!used[to]) used[to]=true,q.push(to);
                    pre[to]=k;
                }
            }
        }
        if(pre[t]==-1) return -1;
        else return flow[t]; 
    }
    void maxflow(int s,int t)
    {
        int d;
        while(bfs(s,t)!=-1)
        {
            d=flow[t];
            int k=t;
            while(k!=s)
            {
                cap[xb[k]]-=d;
                cap[xb[k]^1]+=d;
    
                k=pre[k];
            }
            mflow+=d;
            mcost+=d*dis[t];//每条边上的流量为d,dis[t]为每条边单位流量费用之和
            if(d==0) break;
        }
        return;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&S,&T);
        for(int i=1;i<=m;i++)
        {
            int u,v,w,f;
            scanf("%d%d%d%d",&u,&v,&w,&f);
            add(u,v,w,f);
            add(v,u,0,-f);
        }
    
        maxflow(S,T);
    
        printf("%d %d",mflow,mcost);
        return 0;
    } 
  • 相关阅读:
    HDOJ 1588 Gauss Fibonacci
    HDOJ 1494 跑跑卡丁车
    初识Linux
    大数据教程
    80后上班族
    人际交往,七种心态最惹人讨厌
    商人初步
    分页存储过程
    父母生日
    dephi小技巧
  • 原文地址:https://www.cnblogs.com/dfsac/p/6819724.html
Copyright © 2011-2022 走看看