最小费用最大流——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

  

原文地址:https://www.cnblogs.com/KimKyeYu/p/3223588.html