最小传输费用问题
网络中有两台计算机s和t,现在每秒钟要从s传输大小为F的数据到t。该网络中一共有N太计算机,其中一些计算机之间连有一条单向的通信电缆,每条通信电缆都有对应的一秒内传输的最大数据量。此外,每条电缆还有对应的传输费用,即单位传输费用为d的通信电缆传输大小为x的数据,需要费用为dx。请问传输数据的最小费用。
问题可以转换为一个有向图(计算机为各顶点,传输电缆为边)。每条边有其容量c(e)和费用d(e)。问题可以转换为在保证从s向t有大小为F的流的情况下,使得总费用最小。就是最小费用流问题(最大流情况下每条边添加费用F,求最小值)。
贪心增广,参与网络中的反向边费用应该是原边费用的相反数。需要注意最小费用流不能使用Dijkstra算法因为有负权边。可以使用Bellman-Ford算法。
Bellman-Ford模板:
#define N 1000 #define INF 100000000 struct Edge { int from,to,cap,flow,cost; }; struct MCMF { int n,m,s,t; vectoredges; vectorG ; int inq ;//是否在队列中 int d ;//Bellman-Ford int p ;//上一条弧 int a ;//可改进量 void init(int n) { this->n=n; for(int i=0;i<n;i++) G[i].clear(); edges.clear(); } void addedge(int from,int to,int cap,int cost) { edges.push_back((Edge){from,to,cap,0,cost}); edges.push_back((Edge){to,from,0,0,-cost}); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BellmanFord(int s,int t,int&flow,long long&cost)//沿着最短路增广 { for(int i=0;i<n;i++) d[i]=INF; memset(inq,0,sizeof(inq)); d[s]=0,inq[s]=1,p[s]=0,a[s]=INF; queueq; q.push(s); while(!q.empty()) { int u=q.front();q.pop(); inq[u]=0; for(int i=0;i<G[u].size();i++) { Edge&e=edges[G[u][i]]; if(e.cap>e.flow&&d[e.to]>d[u]+e.cost)//松弛操作 { d[e.to]=d[u]+e.cost; p[e.to]=G[u][i];//记录父边 a[e.to]=min(a[u],e.cap-e.flow);//更新可改进量,等于min{到达u时候的可改进量,e边的残量} if(!inq[e.to]){q.push(e.to);inq[e.to]=1;} } } } if(d[t]==INF)//仍为初始时候的INF,s-t不连通,失败退出 return false; flow+=a[t]; cost+=(long long)d[t]*a[t];//d[t]一方面代表了最短路长度,另一方面代表了这条最短路的单位费用的大小 int u=t; while(u!=s)//逆向修改每条边的流量值 { edges[p[u]].flow+=a[t]; edges[p[u]^1].flow-=a[t]; u=edges[p[u]].from; } return true; } int MincostMaxflow(int s,int t,long long&cost)//返回最大流,同时用引用返回达到最大流时的最小费用 { int flow=0; cost=0; while(BellmanFord(s,t,flow,cost));//直到不存在最短路时停止 return flow; } };
可以通过数学归纳法证明算法为最小费用流(即证明残余网络中没有负圈),证明过程可以详见MIT讲义。
特殊情况
- 对于流量任意
如果需要计算包含负权边的图中流量任意但费用最小的流。可以根据最小流算法中h[i+1](v)>=h[i](v)的性质,在h[i](t)<0时进行增广。 - 对于费用为负
存在负权边需要用Bellman-Ford算法。存在负圈可以利用算法找到负圈并在负圈上尽量增广。通过变形避免负权边的算法(每次增广时如边数相等,通过对所有边费用加上合适常数将边转成非负数)只适用部分情况。
参考
- How to modify Bellman-Ford algorithm for this specific Minimum Cost Flow problem?
- 图论专题小结:最小费用最大流算法
- 《挑战程序设计竞赛》
授权协议:创作共用 署名-非商业性使用 2.5 中国大陆
除注明外,本站文章均为原创;转载时请保留上述链接。
同学,你的代码被转义了,请看第二十五行
谢谢,已经改了。