最小费用最大流
2015-07-16 20:37
295 查看
介绍:
“流”的问题可能不仅仅是流量,还包括“费用”的因素。网络的每一条边(Vi,Vj)除给定了容量Cij外,还给了一个单位流量费用Bij>=0。问题的数学模型是求最大流F,使流的总输送费用B(F)=∑Bij Fij (I,j∈A)取极小值。这就是所谓的最小费用最大流问题。
下图所示是一个公路网,s是仓库所在地,t是物资终点。每一条边都有两个数字,第一个数字表示某段时间通过公路的物资的最多吨数,第二个数字表示每顿物资通过该公路的费用。问怎样安排才能即使得从s运到t的物资最多,又使得总的运输费用最少?
算法思想:
从F=0开始,设已知F是流量V(F)的最小费用流,余下的问题是如何去寻求关于F的最小费用可增广路径。
构造一个加权有向图W(F),它的节点是原网络D的节点,把D中的每一条边(Vi,Vj)变成两个方向相反的边<Vi,Vj>和<Vj,Vi>。定义W(F)中的边权Wij为
于是在网络中寻求关于F的最小费用可增广路径,等价于在加权有向图W(F)中寻求从Vs到Vt的最短路径。
模板:
program mincost;
const
maxn=1000;
maxm=1000*1000*2;
type
edge=record
u,v,r,c,next,op:longint;
end;
var
g:array[1..maxm] of edge;
h:array[1..maxn] of longint;
s,t,flow,cost,a,b,c,d,tot,n,m,i:longint;
procedure add(u,v,r,c:longint);
begin
inc(tot);
g[tot].u:=u;
g[tot].v:=v;
g[tot].r:=r;
g[tot].c:=c;
g[tot].next:=h[u];
h[u]:=tot;
g[tot].op:=tot+1;
inc(tot);
g[tot].u:=v;
g[tot].v:=u;
g[tot].r:=0;
g[tot].c:=-c;
g[tot].next:=h[v];
h[v]:=tot;
g[tot].op:=tot-1;
end;
function spfa(s,t:longint;var flow,cost:longint):boolean;
var
d,p,a:array[1..maxn] of longint;
inq:array[1..maxn] of boolean;
q:array[1..maxm] of longint;
i,u,v,tmp,f,r:longint;
begin
fillchar(d,sizeof(d),$7f);
fillchar(inq,sizeof(inq),false);
d[s]:=0; inq[s]:=true; p[s]:=0;
a[s]:=maxlongint;
f:=1; r:=1; q[f]:=1;
repeat
u:=q[f]; tmp:=h[u];
while tmp<>-1 do
begin
v:=g[tmp].v;
if (g[tmp].r>0) and (d[v]>d[u]+g[tmp].c) then
begin
d[v]:=d[u]+g[tmp].c;
p[v]:=tmp;
a[v]:=min(a[u],g[tmp].r);
if not inq[u] then
begin
inc(r); q[r]:=u; inq[u]:=true;
end;
end;
tmp:=g[tmp].next;
end;
inc(f);
inq[u]:=false;
until f>r;
if d[t]=maxlongint then exit(false);
flow:=flow+a[t];
cost:=cost+d[t]*a[t];
u:=t;
while (u<>s)do
begin
g[p[u]].r:=g[p[u]].r-a[t];
g[g[p[u]].op].r:=g[g[p[u]].op].r+a[t];
u:=g[p[u]].u;
end;
exit(true);
end;
begin
fillchar(h,sizeof(h),$ff);
readln(n,m);
for i:=1 to m do
begin
readln(a,b,c,d);
add(a,b,c,d);
end;
flow:=0;
cost:=0;
s:=1;
t:=n;
while spfa(s,t,flow,cost) do;
writeln(flow,' ',cost);
end.
习题:
poj 2135 Farm Tour
poj 2159
poj 2175 Evacuation Plan
poj 3686 The Windy’s
poj 3068 “Shortest”pair of paths
poj 2195 Going Home
poj 3422 Kaka’s Matrix Travels
poj 2516
具体详见:http://download.csdn.net/download/boyxiejunboy/8911065(不用积分下载哦)
“流”的问题可能不仅仅是流量,还包括“费用”的因素。网络的每一条边(Vi,Vj)除给定了容量Cij外,还给了一个单位流量费用Bij>=0。问题的数学模型是求最大流F,使流的总输送费用B(F)=∑Bij Fij (I,j∈A)取极小值。这就是所谓的最小费用最大流问题。
下图所示是一个公路网,s是仓库所在地,t是物资终点。每一条边都有两个数字,第一个数字表示某段时间通过公路的物资的最多吨数,第二个数字表示每顿物资通过该公路的费用。问怎样安排才能即使得从s运到t的物资最多,又使得总的运输费用最少?
算法思想:
从F=0开始,设已知F是流量V(F)的最小费用流,余下的问题是如何去寻求关于F的最小费用可增广路径。
构造一个加权有向图W(F),它的节点是原网络D的节点,把D中的每一条边(Vi,Vj)变成两个方向相反的边<Vi,Vj>和<Vj,Vi>。定义W(F)中的边权Wij为
于是在网络中寻求关于F的最小费用可增广路径,等价于在加权有向图W(F)中寻求从Vs到Vt的最短路径。
模板:
program mincost;
const
maxn=1000;
maxm=1000*1000*2;
type
edge=record
u,v,r,c,next,op:longint;
end;
var
g:array[1..maxm] of edge;
h:array[1..maxn] of longint;
s,t,flow,cost,a,b,c,d,tot,n,m,i:longint;
procedure add(u,v,r,c:longint);
begin
inc(tot);
g[tot].u:=u;
g[tot].v:=v;
g[tot].r:=r;
g[tot].c:=c;
g[tot].next:=h[u];
h[u]:=tot;
g[tot].op:=tot+1;
inc(tot);
g[tot].u:=v;
g[tot].v:=u;
g[tot].r:=0;
g[tot].c:=-c;
g[tot].next:=h[v];
h[v]:=tot;
g[tot].op:=tot-1;
end;
function spfa(s,t:longint;var flow,cost:longint):boolean;
var
d,p,a:array[1..maxn] of longint;
inq:array[1..maxn] of boolean;
q:array[1..maxm] of longint;
i,u,v,tmp,f,r:longint;
begin
fillchar(d,sizeof(d),$7f);
fillchar(inq,sizeof(inq),false);
d[s]:=0; inq[s]:=true; p[s]:=0;
a[s]:=maxlongint;
f:=1; r:=1; q[f]:=1;
repeat
u:=q[f]; tmp:=h[u];
while tmp<>-1 do
begin
v:=g[tmp].v;
if (g[tmp].r>0) and (d[v]>d[u]+g[tmp].c) then
begin
d[v]:=d[u]+g[tmp].c;
p[v]:=tmp;
a[v]:=min(a[u],g[tmp].r);
if not inq[u] then
begin
inc(r); q[r]:=u; inq[u]:=true;
end;
end;
tmp:=g[tmp].next;
end;
inc(f);
inq[u]:=false;
until f>r;
if d[t]=maxlongint then exit(false);
flow:=flow+a[t];
cost:=cost+d[t]*a[t];
u:=t;
while (u<>s)do
begin
g[p[u]].r:=g[p[u]].r-a[t];
g[g[p[u]].op].r:=g[g[p[u]].op].r+a[t];
u:=g[p[u]].u;
end;
exit(true);
end;
begin
fillchar(h,sizeof(h),$ff);
readln(n,m);
for i:=1 to m do
begin
readln(a,b,c,d);
add(a,b,c,d);
end;
flow:=0;
cost:=0;
s:=1;
t:=n;
while spfa(s,t,flow,cost) do;
writeln(flow,' ',cost);
end.
习题:
poj 2135 Farm Tour
poj 2159
poj 2175 Evacuation Plan
poj 3686 The Windy’s
poj 3068 “Shortest”pair of paths
poj 2195 Going Home
poj 3422 Kaka’s Matrix Travels
poj 2516
具体详见:http://download.csdn.net/download/boyxiejunboy/8911065(不用积分下载哦)
相关文章推荐
- HDU3555Bomb(记忆化搜索)
- 转 C#对话框-打开和保存对话框
- Ubuntu下升级Git以及获取ssh keys的代码
- 算法导论 第十四章:数据结构的扩张
- Java反射机制
- pyQt不同窗体间的值传递(二)——使用信号槽机制
- C++之重载函数
- [主席树]HDOJ2665 && POJ2104 && POJ2761
- chapter18test2
- Spring基础---Spring源码解析以及入门
- [LeetCode]Combination Sum 2(!!!!!)
- Git 的origin和master分析
- Netbeans配合xdebug调试
- ASP.NET - (Session)后台登陆时,判断是不是已经登陆,如果不是,跳转回登陆页
- 习题2-5 分数化小数(decimal)
- 如何跟踪Entity Framework生成的SQL!
- Linux shell命令
- 数据库基础学习3-T-SQL语句
- 装饰器模式和代理模式区别
- Webform——验证控件