数学建模图论
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图
论
一.最短路问题
问题描述:寻找最短路径就是在指定网络中两结点间找一条距离最小的路。
最短路不仅仅指一般地理意义上的距离最短,还可以引申到其它的度量,如时间、费用、线路容量等。
将问题抽象为赋权有向图或无向图G ,边上的权均非负 对每个顶点定义两个标记(()l v ,()z v ),其中:
()l v :表示从顶点到v 的一条路的权 ()z v :v 的父亲点,用以确定最短路的路线
S :具有永久标号的顶点集
1.1Dijkstra 算法:即在每一步改进这两个标记,使最终()l v 为最短路的权 输入:G 的带权邻接矩阵(,)w u v 步骤:
(1) 赋初值:令0()0l u =,对0v u ≠,令()l v =∞,0={u }S ,0i =。
(2) 对每个(\)i i i v S S V S ∈=(即不属于上面S 集合的点),用
min{(),()()}i
u S l v l u w uv ∈+代替()l v ,这里()w uv 表示顶点u 和v 之间边的权值。
计算min{()}i
u S l v ∈,把达到这个最小值的一个顶点记为1i u +,令11{}i i i S S u ++=⋃。
(3) 若1i V =-,则停止;若1i V <-,则用1i +代替i ,转(2)
算法结束时,从0u 到各顶点v 的距离由v 的最后一次编号()l v 给出。
在v 进入i S 之前的编号()l v 叫T 标号,v 进入i S 之后的编号()l v 叫P 标号。
算法就是不断修改各顶点的T 标号,直至获得P 标号。
若在算法运行过程中,将每一顶点获得P 标号所由来的边在图上标明,则算法结束时,0u 至各顶点的最短路也在图上标示出来了。
理解:贪心算法。
选定初始点放在一个集合里,此时权值为0初始点搜索下一个相连接点,将所有相连接的点中离初始点最近的点纳入初始点所在的集合,并更新权值。
然后以新纳入的点为起点继续搜索,直到所有的点遍历。
Matlab代码:
Dijk.m
function[mydistance,mypath]=Dijk(a,sb,db);%sb为起点,db为终点
n=size(a,1);visited(1:n)=0;%n为结点数visited为结点标号
distance(1:n)=inf;distance(sb)=0;%起点到各终点距离的初始化
visited(sb)=1;u=sb;%u为新的P标号顶点(初始点)
parent(1:n)=0;%父节点的初始化
%经过以下一个for..end便可以找到最短路径及该最短路径对应的最短路程
fori=1:n-1%(找所有未标号的点)
id=find(visited==0);%查找未标号的顶点
forv=id%找到一个未标号的点v
ifa(u,v)+distance(u)<distance(v)%uv之间的距离+起点到u的距离小于v到起点的距离(第一次是无穷大的,所以第一次肯定满足,下一次则找比这个点到u距离小的v)
distance(v)=distance(u)+a(u,v);%修改标号值则v到原点的距离(权)修改。
parent(v)=u;%u是v的父节点
end
end
temp=distance;%以上面的distance作为临时的最小距离,如果下一次循环的未标号顶点有更小的距离则替换
temp(visited==1)=inf;%已标号的点距离换为无穷,避免再次搜索
[t,u]=min(temp);%找出距离最小的点(t是最小值,u是最小值的下标)最后一次循环会得到一个最小距离的点
visited(u)=1;%标记已经标号的顶点
end
%下面一段代码用于输出path
mypath=[];%定义mypath为一个空矩阵
ifparent(db)~=0%如果存在路~=为不等于即前面有parent点
t=db;%终点标号赋给t
mypath=[db]%将终点放入路径集合里
whilet~=sb%当终点不是初始点
P=parent(t);%终点的父节点令为P
mypath=[Pmypath];
t=P;%把上一个点的父节点令为下一轮循环的节点,继续搜索父节点
end
end
mydistance=distance(db);%最短路程
main.m
n=29;a=zeros(n);
a(1,2)=2;a(1,10)=2;a(1,13)=180;a(1,20)=216;a(1,27)=131;
a(2,3)=2;
a(3,4)=2;
a(4,5)=2;
a(5,6)=2;
a(6,7)=2;a(6,22)=35;
a(7,8)=2;
a(8,9)=2;
a(9,10)=2;
a(11,12)=2;
a(12,13)=2;
a(13,14)=2;a(13,20)=108;
a(14,15)=2;
a(15,16)=2;
a(16,29)=41; a(17,18)=2;
a(18,19)=2;a(18,23)=309;a(18,21)=134; a(19,20)=2;
a(20,24)=145;a(20,27)=281;a(20,26)=206; a(21,24)=24;
a(22,25)=60;a(22,28)=142; a(23,27)=126; a(24,26)=145; a(26,29)=77; a(28,29)=115; a=a+a';
a(a==0)=inf;%把所有零元素替换成无穷
a([1:n+1:n^2])=0;%对角线元素替换成零,Matlab 中数据是逐列存储的 fori=1:10
[mydistance,mypath]=Dijk(a,21,i);%从公交南北到A1-A10的最短路径 mypath end
二.floyed 算法:
2.1基本思想:直接在图的带权邻接矩阵中用插入顶点的方法依次构造出ν个矩阵(1)
D 、
(2)D 、…、()v D ,使最后得到的矩阵()v D 成为图的距离矩阵,同时也求出插入点矩阵以便
得到两点间的最短路径。
2.2基本原理 2.2.1求距离矩阵
把带权邻接矩W 作为距离矩阵的初值,即(0)(0)()ij v v D d W ⨯== (1)(1)(1)()ij v v D d ⨯=,其中(1)(0)(0)(0)11min{,}ij ij i j d d d d =+ (1)
ij
d 是从i v 到j v 的只允许1v 作为中间点的路径中最短路的长度 (2)(2)(2)()ij v v D d ⨯=,其中(2)(1)(1)(1)22min{,}ij ij i j d d d d =+
(2)
ij
d 是从i v 到j v 的只允许1v 、2v 作为中间点的路径中最短路的长度 %解释:(1)ij d 为从1i j v v v →→;(1)(1)
22i j d d +为从12i
j v v v v →→→
…
(v )()()()v v ij v v D d ⨯=,其中()(1)(1)(1)
min{,}v v v v ij ij iv vj d d d d ---=+
()
v ij
d 是从i v 到j v 的只允许1v 、2v ……v v 作为中间点的路径中最短路的长度,即是从i v 到j v 中间可插入任何顶点的路径中最短路的长,因此()D v 即是距离矩阵。
2.2.2求路径矩阵
在建立距离矩阵的同时可建立路径矩阵R
()ij v v R r ⨯=,ij r 的含义是从i v 到j v 的最短路要经过点号为ij r 的点
(0)(0)()ij v v R r ⨯=,(0)ij r j =%初值
每求得一个()k D 时,按下列方式产生相应的新的()k R 即当k v 被插入任何两点间的最短路径时,被记录在()
k R 中,依次求()
v R
时求得()
v D
,
可由()v R 来查找任何点对之间最短的路径
2.2.3查找最短路径
若()1v ij r p =,则点1p 是点i 到点j 的最短路的中间点。
然后用同样的方法再分头查找。
若:
(1)向点i 追溯得:12()()()
23,,,k v v v ip ip ip k r p r p r p === (2)向点j 追溯得:12()()()12,,,m
v v v p j p j
q j r q r q r j ===
步骤:
(,)D i j :i 到j 的距离 (,)R i j :i 到j 之间的插入点
输入:带权邻接矩阵(,)w i j (1) 赋初值:
对所有,,(,)(,),(,),1i j d i j w i j r i j j k ←←←
(2) 更新(,),(,)d i j r i j
对所有,i j ,
若(,)(,)(,)d i k d k j d i j +<,则(,)(,)(,),(,)d i j d i k d k j r i j k ←+← (3) 若k v =,停止。
否则1k k ←+,转(2) Matlab 代码: floyed.m
%输出最短距离矩阵和最短路径矩阵
function [d,r]=floyd(w) n=length(w); for i=1:n for j=1:n d(i,j)=w(i,j); r(i,j)=j; end end for k=1:n for i=1:n for j=1:n
if d(i,k)+d(k,j)<d(i,j) d(i,j)=d(i,k)+d(k,j); r(i,j)=k; end end end end
myfloyed.m
%输入起点终点得到最短路径和最短距离 %可用循环求多个距离
function[dist,mypath]=myfloyd(a,sb,db);
%a 为邻接矩阵;a(i,j)为顶点i 到j 的直达距离,可以是有向的 %sb 起点,db 终点
%dist 最短路距离mypath 最短路径
n=size(a,1);path=zeros(n);%初始化
fork=1:n%遍历每个点
fori=1:n
forj=1:n%遍历每两点之间的距离
ifa(i,j)>a(i,k)+a(k,j)%如果i,j距离大于从i到k加上从k到j的距离a(i,j)=a(i,k)+a(k,j)%则i,j距离被更新
path(i,j)=k;%k点加入最短路径
end
end
end
end
dist=a(sb,db);
%打印path
parent=path(sb,:);%起点到终点最短路上各顶点的父亲点
parent(parent==0)=sb;%如果父亲点为0则表示该顶点为起点
mypath=db;t=db;%终点放入路径中
whilet~=sb%但某点的父亲点不是不是初始点时,继续循环
p=parent(t);%把该点的父亲点赋给p
mypath=[p,mypath];%把p加入path中
t=p;%把p作为新的点继续循环找父亲点的父亲点
end
可测试数据:
n=29;a=zeros(n);
a(1,2)=2;a(1,10)=2;a(1,13)=180;a(1,20)=216;a(1,27)=131;
a(2,3)=2;
a(3,4)=2;
a(4,5)=2;
a(5,6)=2;
a(6,7)=2;a(6,22)=35;
a(7,8)=2; a(8,9)=2; a(9,10)=2; a(11,12)=2; a(12,13)=2;
a(13,14)=2;a(13,20)=108; a(14,15)=2; a(15,16)=2; a(16,29)=41; a(17,18)=2;
a(18,19)=2;a(18,23)=309;a(18,21)=134; a(19,20)=2;
a(20,24)=145;a(20,27)=281;a(20,26)=206; a(21,24)=24;
a(22,25)=60;a(22,28)=142; a(23,27)=126; a(24,26)=145; a(26,29)=77; a(28,29)=115; a=a+a';
a(a==0)=inf;%把所有零元素替换成无穷
a([1:n+1:n^2])=0;%对角线元素替换成零,Matlab 中数据是逐列存储的 %fori=1:10
[d,r]=floyd(a)%从公交南北到A1-A10的最短路径 %end
二.最小生成树
在连通赋权图上求权最小的生成树。
赋权图的具有最小权的生成树叫做最小生成树。
1.Prim 算法(贪心算法)
图论中的一种算法,可在加权连通图里搜索最小生成树。
意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex(graphtheory)),且其所有边的权值之和亦为最小。
构造连通赋权图()=,,G V E W 的最小生成树(W 是邻接矩阵),设置两个集合P 和Q ,其中P 用于存放G 的最小生成树中的顶点,集合Q 存放G 的最小生成树中的边。
令集合P 的初值为{}1=P v (即初始(出发)点为1v ),集合Q 的初值为Q =∅(空集)。
算法思想:从,p P v V P ∈∈-的边中,选取具有最小权值的边pv ,将顶点v 加入集
合P 中,将边
pv 加入集合Q 中,如此不断重复,直到P V =时,最小生成树构造完毕,这
时集合Q 中包含了最小生成树的所有边。
算法过程:
② {}1P v =,Q =∅。
②while ~P V = 找最小边pv ,其中,p P v V P ∈∈-;
end 代码:
clc
clearall;
%初始化邻接矩阵 a=zeros(7);
a(1,2)=50;a(1,3)=60; a(2,4)=65;a(2,5)=40; a(3,4)=52;a(3,7)=45;
a(4,5)=50;a(4,6)=30;a(4,7)=42; a(5,6)=70; a=a+a';
a(a==0)=inf; %算法主体
result=[];%定义一个空集放结果
p=1;tb=2:length(a);%p 为起点tb 为下一个点
whilesize(result,2)~=length(a)-1%size(result,2)取矩阵result 的第二列 temp=a(p,tb);%所有以1为起点的权值
temp=temp(:);%temp=temp(:)把所有的元素都拿出来,从左到右一列一列的拿,变为一列。
d=min(temp);%最小权值
[jb,kb]=find(a(p,tb)==d,1);%找出起点集到终点集的最小权值的下一个点(第一个)所在位置:行jb 和列kb
j=p(jb);k=tb(kb); result=[result,[j;k;d]]; p=[p,k];
tb(find(tb==k))=[]; end
Kruskal 算法:
从边出发,从所有的边当中选一条最小的边(如果最小的边不止一条,则任选一条即可)然后判断这条边的两个端点是否在同一棵树中(并查集判断),如果已经在同一棵树中,则舍去这条边,因为在这之前已经有一条比这条还短的边连接这两个节点了,如果不在,则把这两个节点连到一棵树中,并且记录下这条边,以此类推,直到边数达到1n -,此时n 个点已经在同一棵树中了,算法结束。
输入:?图G??
输出:?图G 的最小生成树?? 具体流程:??
(1)选()1e E G ∈,使得1e 是权值最小的边
(2)若12,...,i e e e 已选好,则从(){}12,,...,i E G e e e -中选取1i e +,使得 ①{}121,,...,,i i e e e e +中无圈;
②1i e +是(){}12,,...,i E G e e e -中权值最小的边。
(3)直到选得1V e -为止 代码: clc
clearall;
%初始化邻接矩阵 a(1,[2,3])=[50,60]; a(2,[4,5])=[65,40]; a(3,[4,7])=[52,45];
a(4,[5,6])=[50,30];%邻接矩阵另一种输入方式 a(4,7)=42;a(5,7)=70; [i,j,b]=find(a);%a 中非零值
data=[i';j';b'];%存放所有非零值位置及值 index=data(1:2,:);%存放非零的两点
loop=length(a)-1;
result=[];
%算法主体
whilelength(result)<loop
temp=min(data(3,:));%权值最小
flag=find(data(3,:)==temp);
flag=flag(1);
v1=index(1,flag);%权值最小两点的第一个点
v2=index(2,flag);%权值最小两点的第二个点
ifv1~=v2%如果两点不是同一个点
result=[result,data(:,flag)];%加入结果集中
end
index(find(index==v2))=v1;%让两个端点相同,则后面搜索时不再被选
data(:,flag)=[];
index(:,flag)=[];
end
result
三.网络最大流
在一定条件下,求解给定系统的最大流量。
应用背景:铁路运输系统中的车辆流,城市给排水系统的水流问题,控制系统中的信息流问题,常见的人流,物流,水流,气流,电流,现金流等。
为解决该问题,首先引入一些必要的概念:
1.网络与流
给一个有向图(),D V A =,其中A 为弧集,在V 中指定了一点,称为发点(记为s v ),另一点称为收点(记为t v ),其余的点叫中间点,对于每一条弧()
,i j v v A ∈,对应有一个(,)0i j c v v ≥(或简写为ij c ),称为弧的容量。
通常把这样的有向图D 叫做一个网络,记为(),,D V A C =,其中{}ij C c =。
所谓网络上的流,是指定义在弧集合{}{}(,)ij i j f f f v v ==,并称ij f 为弧(),i j v v 上的流量。
2.可行流与最大流
满足下列条件的流f 称为可行流:
(1) 容量限制条件:对每一弧()
,0i j ij ij v v A f c ∈≤≤,。
(2) 平衡条件:对于中间点,流出量?流入量,即对于每个(),i i s t ≠,有 :(,):(,)0i j j i ij ji j v v A j v v A f f ∈∈-=∑∑?,
对于发点s v ,记
?
:(,):(,)()s j j s sj js j v v A j v v A f f v f ∈∈-=∑∑,
对于收点t v ?,记
:(,):(,)()t j j t tj jt j v v A j v v A f f v f ∈∈-=-∑∑,
式中:()v f 为这个可行流的流量,即发点的净输出量。
可行流总是存在的,如零流。
最大流问题可以写为如下的线性规划模型:
??增广路
给定一个可行流{}
ij f f =,把网络中使ij ij f c =的弧称为饱和弧,使ij ij f c <的弧称为非饱和弧。
把0ij f =称为零流弧,0ij f >的弧称为费零流弧。
若μ是网络中联接发点s v 和收点t v 的一条路,定义路的方向是从s v 到t v ,则路上的弧被分为两类:一类是弧的方向与路的方向一致,称为前向弧,前向弧的全体即为+μ;另一类弧与路的方向相反称为后向弧,后向弧的全体称为μ-。
定义:设f 是一个可行流,μ是从s v 到t v 的一条路,若μ满足:前向弧是非饱和弧,后向弧是非零流弧,则称μ为(关于可行流f )一条增广路。
Ford-Fulkerson 算法流程:
其中,每个顶点x v 的标号值有两个,第一个标号值表示在可能的增广路上,x v 的前驱顶点;x v 的第二个编号值记为δ,标志在可能的增广路上可以调整的流量。
初始化给发点s v 标号()0∞,,对已标号顶点x v 的邻接顶点按以下规则标号:
①若(),x y v v A ∈,且xy xy f c >时,令{}
min ,y xy xy x c f δδ=-,则给顶点y v 标号为(),x y v δ,若xy xy f c =,则不给顶点y v 标号。
②(),y x v v A ∈,且0yx f >,令{}=min ,y yx x f δδ,则给y v 标号为(),x y v δ-,这里第一个标号值x v -,表示在可能的增广路上,()
,y x v v 为反向弧;若0yx f =,则不给y v 标号。
增流过程:
① 令y t v v =。
② 若y v 的标号为(),x t v δ,则x y x y t f f δ=+;
若y v 的标号为(),x t v δ-,则y x y x t f f δ=-。
Ford_Fulkerson.m
%n 表示节点数,C 表示容量矩阵
function[f,wf,No]=Ford_Fulkerson(n,C)
for(i=1:n)for(j=1:n)f(i,j)=0;end;end%取初始可行流f 为零流
for(i=1:n)No(i)=0;d(i)=0;end%No,d 记录标号
while(1)
No(1)=n+1;
d(1)=Inf;%给发点vs 标号
while(1)pd=1;%标号过程
for(i=1:n)if(No(i))%选择一个已标号的点vi
for(j=1:n)if(No(j)==0&f(i,j)<C(i,j))%对于未给标号的点vj,当vivj 为非饱和弧时 No(j)=i;d(j)=C(i,j)-f(i,j);pd=0;
if(d(j)>d(i))d(j)=d(i);end
elseif(No(j)==0&f(j,i)>0)%对于未给标号的点vj,当vjvi 为非零流弧时
No(j)=-i;d(j)=f(j,i);pd=0;
if(d(j)>d(i))d(j)=d(i);end;end;end;end;end
if(No(n)|pd)break;end;end%若收点vt得到标号或者无法标号,终止标号过程
if(pd)break;end%vt未得到标号,f已是最大流,算法终止
dvt=d(n);t=n;%进入调整过程,dvt表示调整量
while(1)
if(No(t)>0)f(No(t),t)=f(No(t),t)+dvt;%前向弧调整
elseif(No(t)<0)f(No(t),t)=f(No(t),t)-dvt;end%后向弧调整
if(No(t)==1)for(i=1:n)No(i)=0;d(i)=0;end;break;end%当t的标号为vs时,终止调整过程
t=No(t);
end;
end;%继续调整前一段弧上的流f
wf=0;for(j=1:n)wf=wf+f(1,j);end%计算最大流量
f%显示最大流
wf%显示最大流量
No%显示标号,由此可得最小割,程序结束
输入:
C=[];
n=;
四.最小费用最大流
最小费用最大流问题是经济学和管理学的一类典型的基本问题。
在一个网络中每条路径都存在“容量”和“费用”两个限制条件,此类问题是想寻找出:车辆从A地到B地,选择合适的路径及考虑分配路径的流量,使其能够在流量最大的前提下,达到所用的费用最小的要求。
假设n辆卡车要从A地到B地运送物品,由于每条路段都存在不同的收费情况,每条
路能容纳的车的数量也有一定限制,最小费用最大流问题指如何分配卡车的出发路径可以使费用降到最低,物品又能准确全部的送达。
物流成本最小问题称为最小费用流问题,在现实生活中有很多的应用,一般把其归为一类网络优化问题。
可以把容量作为流,费用作为时间代价,来研究交通运输问题。
最小费用最大流算法包含很多经典的算法和流程,本文主要采用最大流算法和最小费用最大流对偶算法。
1. 模型的建立
给定网络()=,,,,,N V E c w s t ,每一条弧上(),i j v v 属于E ,除了已给容量ij c 外,还给了一个单位流量的费用(),0i j w v v ≥(简记为ij w )。
所谓最小费用最大流问题就是要求一个最大流f 是N 的一个可行流,p 为s v 到t v (关于流f ),使得流的总输送费用取最小值。
2.对偶法求解最小费用最大流问题
定义:已知网络()=,,,,,N V E c w s t ,f 是N 的一个可行流,p 为s v 到t v (关于流f )的可增广路径,称()()()ij ij
w p w p w p +-
=-∑∑为路径p 的费用。
若*p 是从s v 到t v 所有可增广路径中费用最小的路径,则称*p 为最小费用可增广路径。
定理:若f 是流量为()v f 的最小费用流,p 是关于f 的从s v 到t v 的一条最小费用可增广路径,则f 经过p 调整流量Q 得到新的可行流'f (记为'f f Q =+),一定是流量为()v f Q +的可行流中的最小费用流。
3.对偶法的基本思路
① 取{}0f =
② 寻找从s v 到t v 的一条最小费用可增广路径p 。
若不存在p ,则f 为N 中的最小费用最大流,算法结束。
若存在p ,则用求最大流的方法将f 调整成*f ,使(*)()v f v f Q =+
,并将*
f 赋值给f ,转②
n=6;
C=[080700
009500
000205
000090
0060010
000000];%弧容量
b=[020800
002500
000106
000030
004007
000000];%弧容量
wf=0;wf0=Inf;%wf 表示最大流量,wf0表示预定的流量值
for(i=1:n)for(j=1:n)f(i,j)=0;end;end%取初始可行流f 为零流
while(1)
for(i=1:n)for(j=1:n)if(j~=i)a(i,j)=Inf;end;end;end%构造有向赋权图
for(i=1:n)for(j=1:n)if(C(i,j)>0&f(i,j)==0)a(i,j)=b(i,j);
elseif(C(i,j)>0&f(i,j)==C(i,j))a(j,i)=-b(i,j);
elseif(C(i,j)>0)a(i,j)=b(i,j);a(j,i)=-b(i,j);end;end;end
for(i=2:n)p(i)=Inf;s(i)=i;end%用Ford算法求最短路,赋初值
for(k=1:n)pd=1;%求有向赋权图中vs到vt的最短路
for(i=2:n)for(j=1:n)if(p(i)>p(j)+a(j,i))p(i)=p(j)+a(j,i);s(i)=j;pd=0;end;end;end
if(pd)break;end;end%求最短路的Ford算法结束
if(p(n)==Inf)break;end%不存在vs到vt的最短路,算法终止.注意在求最小费dvt=Inf;t=n;%进入调整过程,dvt表示调整量
while(1)%计算调整量
if(a(s(t),t)>0)dvtt=C(s(t),t)-f(s(t),t);%前向弧调整量
elseif(a(s(t),t)<0)dvtt=f(t,s(t));end%后向弧调整量
if(dvt>dvtt)dvt=dvtt;end
if(s(t)==1)break;end%当t的标号为vs时,终止计算调整量
t=s(t);end%继续调整前一段弧上的流f
pd=0;if(wf+dvt>=wf0)dvt=wf0-wf;pd=1;end%如果最大流量大于或等于预定的流t=n;while(1)%调整过程
if(a(s(t),t)>0)f(s(t),t)=f(s(t),t)+dvt;%前向弧调整
elseif(a(s(t),t)<0)f(t,s(t))=f(t,s(t))-dvt;end%后向弧调整
if(s(t)==1)break;end%当t的标号为vs时,终止调整过程
t=s(t);end
if(pd)break;end%如果最大流量达到预定的流量值
wf=0;for(j=1:n)wf=wf+f(1,j);end;end%计算最大流量
zwf=0;for(i=1:n)for(j=1:n)zwf=zwf+b(i,j)*f(i,j);end;end%计算最小费用
f%显示最小费用最大流
wf%显示最小费用最大流量zwf%显示最小费用,程序结束。