• MCMF(最小费用最大流)


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

     1 //最小费用最大流模版.求最大费用最大流建图时把费用取负即可。
     2 //无向边转换成有向边时需要拆分成两条有向边。即两次加边。
     3 const int maxn = 1010;
     4 const int maxm = 1000200;
     5 const int inf = 1000000000;
     6 struct Edge
     7 {
     8     int v, cap, cost, next;
     9 }p[maxm << 1];
    10 int e, sumFlow, n, m, st, en;
    11 int head[maxn], dis[maxn], pre[maxn];
    12 bool vis[maxn];
    13 void init()
    14 {
    15     e=0;
    16     memset(head,-1,sizeof(head));
    17 }
    18 void addEdge(int u,int v,int cap,int cost)
    19 {
    20     p[e].v = v; p[e].cap = cap; p[e].cost = cost;
    21     p[e].next = head[u]; head[u] = e++;
    22     p[e].v = u; p[e].cap = 0; p[e].cost = - cost;
    23     p[e].next = head[v]; head[v] = e++;
    24 }
    25 bool spfa(int s,int t, int n)
    26 {
    27     int u,v;
    28     queue<int>q;
    29     memset(vis,false,sizeof(vis));
    30     memset(pre,-1,sizeof(pre));
    31     for(int i = 0; i <= n; ++i) 
    32         dis[i] = inf;
    33     vis[s] = true;
    34     dis[s] = 0;
    35     q.push(s);
    36     while(!q.empty())
    37     {
    38         u = q.front();
    39         q.pop();
    40         vis[u] = false;
    41         for(int i = head[u]; i != -1; i = p[i].next)
    42         {
    43             v = p[i].v;
    44             if(p[i].cap && dis[v] > dis[u] + p[i].cost)
    45             {
    46                 dis[v] = dis[u] + p[i].cost;
    47                 pre[v] = i;
    48                 if(!vis[v])
    49                 {
    50                     q.push(v);
    51                     vis[v]=true;
    52                 }
    53             }
    54         }
    55      }
    56      if(dis[t] == inf) 
    57          return false;
    58      return true;
    59 }
    60 int MCMF(int s,int t,int n)
    61 {
    62     int flow = 0; // 总流量
    63     int minflow, mincost;
    64     mincost=0;
    65     while(spfa(s,t,n))
    66     {
    67         minflow = inf + 1;
    68         for(int i = pre[t]; i != -1; i = pre[p[i^1].v])
    69             if(p[i].cap < minflow)
    70                 minflow = p[i].cap;
    71         flow += minflow;
    72         for(int i=pre[t];i!=-1;i=pre[p[i^1].v])
    73         {
    74             p[i].cap -= minflow;
    75             p[i^1].cap += minflow;
    76         }
    77         mincost += dis[t] * minflow;
    78     }
    79     sumFlow = flow; // 最大流
    80     return mincost;
    81 }
  • 相关阅读:
    Codeblocks的常用Debug快捷键
    大整数乘法(POJ2389)
    简单深搜
    Windows安装时的几个命令(摘录)
    模拟栈的回溯,完全二叉树搜索,(ZOJ1004)
    生理周期,POJ(1006)
    next_permutation,POJ(1256)
    计算次数,POJ(1207)
    模拟,找次品硬币,Counterfeit Dollar(POJ 1013)
    深搜(DFS),Image Perimeters
  • 原文地址:https://www.cnblogs.com/Missa/p/3030512.html
Copyright © 2020-2023  润新知