MCMF最小费用最大流模板

来源:互联网 发布:oracle数据库架构 编辑:程序博客网 时间:2024/06/04 23:36

原文网址:http://www.cnblogs.com/Missa/archive/2013/04/19/3030512.html

注:流量和费用两个限制条件

在一个网络中每段路径都有“容量”和“费用”两个限制的条件下,此类问题的研究试图寻找出:流量从A到B,如何选择路径、分配经过路径的流量,可以达到所用的费用最小的要求。如n辆卡车要运送物品,从A地到B地。由于每条路段都有不同的路费要缴纳,每条路能容纳的车的数量有限制,最小费用最大流问题指如何分配卡车的出发路径可以达到费用最低,物品又能全部送到。


//最小费用最大流模版.求最大费用最大流建图时把费用取负即可。//无向边转换成有向边时需要拆分成两条有向边。即两次加边。const int maxn = 1010; //点的最大值const int maxm = 1000200; //边的最大值const int inf = 0x3f3f3f3f;struct Edge{    int v, cap, cost, next;}p[maxm << 1];int e, sumFlow, n, m, st, en; //sumFlow记录最大流 n是点的个数int head[maxn], dis[maxn], pre[maxn];bool vis[maxn];void init(){    e=0;    memset(head,-1,sizeof(head));}void addEdge(int u,int v,int cap,int cost){    p[e].v = v; p[e].cap = cap; p[e].cost = cost;    p[e].next = head[u]; head[u] = e++;    p[e].v = u; p[e].cap = 0; p[e].cost = - cost;    p[e].next = head[v]; head[v] = e++;}bool spfa(int s,int t, int n){    int u,v;    queue<int>q;    memset(vis,false,sizeof(vis));    memset(pre,-1,sizeof(pre));    for(int i = 0; i <= n; ++i)         dis[i] = inf;    vis[s] = true;    dis[s] = 0;    q.push(s);    while(!q.empty())    {        u = q.front();        q.pop();        vis[u] = false;        for(int i = head[u]; i != -1; i = p[i].next)        {            v = p[i].v;            if(p[i].cap && dis[v] > dis[u] + p[i].cost)            {                dis[v] = dis[u] + p[i].cost;                pre[v] = i;                if(!vis[v])                {                    q.push(v);                    vis[v]=true;                }            }        }     }     if(dis[t] == inf)          return false;     return true;}int MCMF(int s,int t,int n){    int flow = 0; // 总流量    int minflow, mincost;    mincost=0;    while(spfa(s,t,n))    {        minflow = inf + 1;        for(int i = pre[t]; i != -1; i = pre[p[i^1].v])            if(p[i].cap < minflow)                minflow = p[i].cap;        flow += minflow;        for(int i=pre[t];i!=-1;i=pre[p[i^1].v])        {            p[i].cap -= minflow;            p[i^1].cap += minflow;        }        mincost += dis[t] * minflow;    }    sumFlow = flow; // 最大流    return mincost;}