• 最小费用最大流——maxflow+SPFA


    最小费用最大流:

      即在所有最大流中,要求得到最少费用。(每条边有两个参数:容量cap, 费用cost)。

      解法:每次找到费用最小的增广路。(即以费用为权的最短路)

         仅需将最大流中的 bfs 替换为SPFA(因为有负权)。

    代码如下:

     1 #define MAXN 1005
     2 #define MAXM 10005
     3 #define INF 0x3f3f3f3f
     4 using namespace std;
     5 
     6 struct P{
     7     int u, v, cap, cost, next;        //容量cap, 单位流量费用cost。
     8 }e[MAXM*4];        //无向边的话*4
     9 int id[MAXM];    //id[v]存放某条边(u,v)在e[]中的位置。
    10 
    11 int head[MAXN], ie;
    12 int dist[MAXN];    //费用为权
    13 int vis[MAXN];
    14 int n, m;
    15 
    16 void add(int u, int v, int cap, int cost){
    17     e[ie].u=u, e[ie].v=v, e[ie].cap=cap, e[ie].cost=cost;
    18     e[ie].next=head[u],   head[u] = ie++;
    19     e[ie].u=v, e[ie].v=u, e[ie].cap=0,   e[ie].cost=-1*cost;    //反向边cap=0, cost相反;
    20     e[ie].next=head[v],   head[v] = ie++;
    21 }
    22 
    23 bool SPFA(int s, int t){
    24     queue <int> q;
    25     memset(dist, 0x3f, sizeof(dist));
    26     memset(vis, 0, sizeof(vis));
    27     dist[s] = 0;
    28     vis[s] = 1;
    29     q.push(s);
    30     while(!q.empty()){
    31         int u=q.front();
    32         q.pop();
    33         vis[u] = 0;
    34         for(int i=head[u]; i!=-1; i=e[i].next){
    35             int v = e[i].v;
    36             if(e[i].cap>0 && dist[v] > dist[u]+e[i].cost){
    37                 dist[v] = dist[u]+e[i].cost;
    38                 id[v] = i;        //!!
    39                 if(!vis[v]){
    40                     vis[v] = 1;
    41                     q.push(v);
    42                 }
    43             }        
    44         }
    45     }
    46     if(dist[t] == INF)
    47         return false;
    48     else
    49         return true;
    50 }
    51 
    52 int MCMF(int s, int t){
    53     int flow=0, cost=0, d;
    54     while(SPFA(s, t)){    
    55         d = INF;
    56         for(int i=t; i!=s; i=e[id[i]].u)
    57             d = min(d, e[id[i]].cap);
    58         for(int i=t; i!=s; i=e[id[i]].u){
    59             e[id[i]].cap -= d;
    60             e[id[i]^1].cap += d;    //由于ie从0开始,    若e[id[i]]表示边(u, v), 那么 e[id[i]^1]表示边(v, u);    
    61         }
    62         flow += d;
    63         cost += dist[t]*d;
    64     }
    65     return cost;
    66 }
    67 
    68 int main()
    69 {    
    70     memset(head, -1, sizeof(head));        
    71     ie = 0;        //必须从0开始
    72 
    73     
    74     return 0;
    75 }
    View Code

      

  • 相关阅读:
    10000个线程更新同一行数据
    CountDownLatchTest
    创建 oracle dblin
    extjs日期控件使用
    JAVA Date超强工具类,可直接取代util.Date使用
    JSP&Servlet学习手册
    JAVA 文本 TXT 操作工具类
    Leetcode 526.优美的排列
    Leetcode 525.连续数组
    Leetcode 523.连续的子数组和
  • 原文地址:https://www.cnblogs.com/KimKyeYu/p/3223588.html
Copyright © 2020-2023  润新知