最小费用最大流详解与模板

来源:互联网 发布:mac怎么安装ipython 编辑:程序博客网 时间:2024/05/17 05:19

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


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

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

MCMF模板:

#include<iostream>#include<algorithm>#include<string>#include<sstream>#include<set>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<functional>using namespace std;#define N 1000#define INF 100000000struct Edge{    int from,to,cap,flow,cost;    Edge(int u,int v,int ca,int f,int co):from(u),to(v),cap(ca),flow(f),cost(co){};};struct MCMF{    int n,m,s,t;    vector<Edge> edges;    vector<int> G[N];    int inq[N];//是否在队列中    int d[N];//距离    int p[N];//上一条弧    int a[N];//可改进量    void init(int n)//初始化    {        this->n=n;        for(int i=0;i<n;i++)            G[i].clear();        edges.clear();    }    void addedge(int from,int to,int cap,int cost)//加边    {        edges.push_back(Edge(from,to,cap,0,cost));        edges.push_back(Edge(to,from,0,0,-cost));        int m=edges.size();        G[from].push_back(m-2);        G[to].push_back(m-1);    }    bool SPFA(int s,int t,int &flow,int &cost)//寻找最小费用的增广路,使用引用同时修改原flow,cost    {        for(int i=0;i<n;i++)            d[i]=INF;        memset(inq,0,sizeof(inq));        d[s]=0;inq[s]=1;p[s]=0;a[s]=INF;        queue<int> Q;        Q.push(s);        while(!Q.empty())        {            int u=Q.front();            Q.pop();            inq[u]--;            for(int i=0;i<G[u].size();i++)            {                Edge& e=edges[G[u][i]];                if(e.cap>e.flow && d[e.to]>d[u]+e.cost)//满足可增广且可变短                {                    d[e.to]=d[u]+e.cost;                    p[e.to]=G[u][i];                    a[e.to]=min(a[u],e.cap-e.flow);                    if(!inq[e.to])                    {                        inq[e.to]++;                        Q.push(e.to);                    }                }            }        }        if(d[t]==INF) return false;//汇点不可达则退出        flow+=a[t];        cost+=d[t]*a[t];        int u=t;        while(u!=s)//更新正向边和反向边        {            edges[p[u]].flow+=a[t];            edges[p[u]^1].flow-=a[t];            u=edges[p[u]].from;        }        return true;    }    int MincotMaxflow(int s,int t)    {        int flow=0,cost=0;        while(SPFA(s,t,flow,cost));        return cost;    }};int main(){    MCMF mcmf;    return 0;}
4 1
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机号销户话费怎么办 微信Q币充错怎么办 淘宝q币充错了怎么办 移动充值错误怎么办 qq忘记密码怎么办登陆 sql数据库满了怎么办 微信充值话费不到账怎么办 填报志愿密码错误怎么办 校园卡被冻结了怎么办 充值卡密码丢了怎么办 联通手机号码不支持开黄钻怎么办 手机qq加载失败怎么办 qq红包额度上限怎么办 qq红包超出限额怎么办 qq红包超过限额怎么办 红包过期没退回怎么办 qb充值错了号码怎么办 天猫q币充值被骗怎么办 微信充错了q币怎么办 qq钱包没银行卡怎么办 qq钱包被限制怎么办 充流量未到账怎么办 云客服被冻结怎么办 联通话费注销了怎么办 我的话费太多怎么办 lol充错账号怎么办 支付宝手机充值没到账怎么办 支付宝限额10000怎么办 米币超过限制怎么办 忘记财付通支付密码怎么办 支付宝忘记登陆密码怎么办 三位数密码忘记了怎么办 登入密码忘记怎么办 电脑登录忘记密码怎么办 支付宝忘记密码怎么办 密码箱忘了密码怎么办 信用卡忘了密码怎么办 我没有财付通钱没有了怎么办 发红包忘记密码怎么办 手机怎么办理财付通 忘记qq红包密码怎么办