最小费用最大流:
即在所有最大流中,要求得到最少费用。(每条边有两个参数:容量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 }