在一个网络中每段路径都有“容量”和“费用”两个限制的条件下,此类问题的研究试图寻找出:流量从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 }