最小费用最大流.docx
- 文档编号:24709041
- 上传时间:2023-05-31
- 格式:DOCX
- 页数:18
- 大小:80.10KB
最小费用最大流.docx
《最小费用最大流.docx》由会员分享,可在线阅读,更多相关《最小费用最大流.docx(18页珍藏版)》请在冰豆网上搜索。
最小费用最大流
云南大学数学与统计学实验教学中心
实验报告
课程名称:
运筹学实验
学期:
2012~2013学年第二学期
成绩:
指导教师:
葛瑜
学生姓名:
卢富毓
学生学号:
20101910072
实验名称:
最小费用最大流
实验要求:
必做
实验学时:
2学时
实验编号:
08
实验日期:
2013/4/30
完成日期:
2013/6/14
学院:
数学与统计学院
专业:
信息与计算科学
年级:
2010级
一、实验目的
给定网络D=(V,A,C),每一条弧
上,除了已给容量
,还给了一个单位流量的费用
,编制程序,找到从发点Vs到收点Vt的最小费用最大流。
二、实验环境
VS2010(C++)
三、实验内容
P275
例15:
以图10-28为例,求最小费用最大流。
弧旁数字为
四、实验过程
A、最小费用最大流的实现步骤:
在最小费用最大流的实现中,其实大的来说就两个步骤:
在图中寻找最短路径;路径调整。
当然在这其中涉及到了流量的如何调整,以及图中边的方向变化。
在寻找最短路径的增广链中,需要将从始点到终点的每一条增广链找到!
知道没有增广链了程序才能停止。
具体做法如下(课本P275):
由前面的实验可知,寻求最大流的方法是从某个可行流f(我采用的是零流),找到关于这个流的一条增广链,据此调整f,对新的可行流试图寻求关于它的增广链,如此反复直到最大流,现在还要求最小费用的最大流,设已知f是流量v(f)的最小费用流,余下的问题就是去寻求关于f的最小费用增广链。
构造一个赋权有向图W(f),顶点是原网络图D上的顶点,而把D中的每一条弧变成两个方向上的弧,定义弧上的权为
在网络D中寻求关于f的最小费用增广链等价于在赋权有向图W(f)中,寻求从到的最短路。
因此有如下算法:
开始取f(0)=0,一般情况下若在第k-1步得到最小费用流f(k-1),则构造赋权有向图W(f(k-1)),在W(f(k-1))中,寻求从vs到vt的最短路。
若不存在最短路(即最短路径是∞),则f(k-1)就是最小费用最大流;若存在最短路,则在原网络D中得到相应的增广链,在增广链μ上对f(k-1)进行调整
B、将上面算法编写实现运行结果如下图:
a、输入各边:
输入的结果为红色字体
b、初始化后的到结果:
上图中得到的图的关系与课本例题中的一样!
所以创建图形正确!
c、寻找最短增广链:
d、最后的最小费用最大流的图如下:
图中得到的结果与课本276页的结果一致!
说明程序运算得到的结果正确!
五、实验总结
虽说看课本P276的有点复杂,同时来自己手动做的时候更是会出现思路混乱!
但是运用程序来解决后,可以让自己将思路理清,当然前面在做的时候忽略了最小费用最大流中有负值存在,Dijkstra算法失效,得时候P266中的算法来实现!
六、源代码
源代码如下:
//图的顶点结构如下:
//-----------------------------------
//|vex|formerNode|MinPathWeight|
//-----------------------------------
//图的边的结构如下:
//----------------------
//|weight|flows|cost|
//----------------------
#include
#include
#include
usingnamespacestd;
#defineMax_vex100
#defineM1000
//SetTextC1是原来的颜色
//SetTextC2是设置的输出输入颜色
#defineSetTextC1SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE)
#defineSetTextC2SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN)
#defineSetTextC3SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN|FOREGROUND_BLUE)//靛色
#defineSetTextC4SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED)//红色
#defineSetTextC5SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_BLUE)
#defineSetTextC6SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE)//无亮度的白色
#defineSetTextC7SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN)
classArcll{//边上值
public:
doubleweight;//容量
doubleflows;//流量
doublecost;
};
classVex{//顶点值
public:
stringvexs;//顶点名称
intformerVex;//前驱节点的下标
doubleMinPathWeight;//初始点到每个节点的最短路径
};
classGraphics{//创建一个图的类
private:
intvexnum;//顶点数
intarcnum;//边数
Vexvexs[Max_vex];//存储定点名称
Arcllarcs[Max_vex][Max_vex];//边数
public:
voidCreateGraphics(Graphics&G);//创建一个图
intLocateIndex(GraphicsG,stringv);//寻找下标
voidstart(Graphics&G);
boolShorttestPath(Graphics&G,intsindex,intfindex);//求最小费用增广链
voidDisplay(GraphicsG);//打印各边的流量和容量信息
voidMCMSInfo(GraphicsG,GraphicsG1);//打印最小费用最大流相关信息
};
//方法实现
//找到相应顶点的下标
intGraphics:
:
LocateIndex(GraphicsG,stringv){
inti=0;
for(i=0;i if(G.vexs[i]pare(v)==0){ returni; } } return-1; } //创建一个有向图 voidGraphics: : CreateGraphics(Graphics&G){ inti,j,k; stringVi,Vj; doublec,w;//费用、容量 SetTextC1; cout<<"-------------------------创建有向图的存储-------------------------------"< cout<<"请输入顶点数: "; SetTextC4;//设置颜色 cin>>G.vexnum; SetTextC1;//设置颜色 cout<<"请输入图的边数: "; SetTextC4; cin>>G.arcnum; SetTextC1; cout<<"请输入顶点名: "; SetTextC4; for(i=0;i cin>>G.vexs[i].vexs; G.vexs[i].formerVex=-1; G.vexs[i].MinPathWeight=0; } SetTextC1; for(i=0;i for(j=0;j if(i==j){ G.arcs[i][j].cost=0; }else{ G.arcs[i][j].cost=M; } G.arcs[i][j].weight=0; G.arcs[i][j].flows=0; } } for(k=0;k cout<<"请输入第"< "; SetTextC4; cin>>Vi>>Vj>>c>>w; SetTextC1; i=LocateIndex(G,Vi); j=LocateIndex(G,Vj); if(i==-1||j==-1){ cout<<"输入错误! 请检查..."< return; } G.arcs[i][j].weight=w; G.arcs[i][j].cost=c; } cout< cout<<"各顶点的关系: "< SetTextC2;//绿色 for(i=0;i if(i==0){ cout<<"\t\t"< }else{ cout<<"\t"< } } cout< SetTextC3; for(i=0;i SetTextC2; cout<<"\t"< SetTextC3; for(j=0;j if(G.arcs[i][j].weight==0){ SetTextC6; cout<<"\t"<<" SetTextC3; }else{ if(G.arcs[i][j].weight>9){ cout<<"\t<"< }else{ cout<<"\t<"< } } } cout< } SetTextC1; cout< "< } //===================最小费用最大流====================== voidGraphics: : start(Graphics&G){ intsindex,findex;//初始点和结束点的下标 stringsvex,fvex; //创建有向图 G.CreateGraphics(G); GraphicsG1=G; cout<<"请输入始点和结束点: "; SetTextC4; cin>>svex>>fvex; SetTextC1; sindex=LocateIndex(G,svex);//初始点的下标 findex=LocateIndex(G,fvex);//结束点的下标 while(ShorttestPath(G,sindex,findex));//求最小费用增广链 MCMSInfo(G,G1); } boolGraphics: : ShorttestPath(Graphics&G,intsindex,intfindex){//寻找最短路的增广链 inti,j,k=G.vexnum; boolb=true; doublemin=M; int*r; r=newint[G.vexnum]; for(i=0;i G.vexs[i].MinPathWeight=G.arcs[sindex][i].cost; if(i! =sindex&&G.vexs[i].MinPathWeight! =M){ G.vexs[i].formerVex=sindex; } } while(b){ b=false; for(i=0;i if(i! =sindex){ for(j=0;j if((G.vexs[i].MinPathWeight+G.arcs[i][j].cost) &&G.arcs[i][j].cost! =M){ G.vexs[j].MinPathWeight=G.vexs[i].MinPathWeight+G.arcs[i][j].cost; G.vexs[j].formerVex=i; b=true; } } } } } if(G.vexs[findex].MinPathWeight==M){//已找到最小费用最大流 cout< cout<<"已得到最小费用最大流! ! ! "< returnfalse; }else{ for(i=findex;i! =-1;){//打印最短路,并求的增广链的调整值 r[--k]=i; j=G.vexs[i].formerVex; if(j==-1)break; if(G.arcs[j][i].cost! =0){ if((G.arcs[j][i].weight-G.arcs[j][i].flows) min=G.arcs[j][i].weight-G.arcs[j][i].flows; } }else{ if(G.arcs[i][j].flows min=G.arcs[i][j].flows; } } i=j; } cout< "; SetTextC5;//紫色 for(i=k;i //调整最短路径上的流量值,课本266页的算法 cout< if(i==G.vexnum-2){ cout< } if(G.arcs[r[i]][r[i+1]].cost! =0){ G.arcs[r[i]][r[i+1]].flows=G.arcs[r[i]][r[i+1]].flows+min; G.arcs[r[i+1]][r[i]].cost=-G.arcs[r[i]][r[i+1]].cost; G.arcs[r[i+1]][r[i]].weight=G.arcs[r[i]][r[i+1]].weight; G.arcs[r[i+1]][r[i]].flows=-G.arcs[r[i]][r[i+1]].flows; if(G.arcs[r[i]][r[i+1]].flows==G.arcs[r[i]][r[i+1]].weight){ G.arcs[r[i]][r[i+1]].cost=M; } }else{ G.arcs[r[i+1]][r[i]].flows=G.arcs[r[i+1]][r[i]].flows-min; G.arcs[r[i]][r[i+1]].cost=-G.arcs[r[i+1]][r[i]].cost; G.arcs[r[i+1]][r[i]].weight=G.arcs[r[i]][r[i+1]].weight; G.arcs[r[i+1]][r[i]].flows=-G.arcs[r[i]][r[i+1]].flows; if(G.arcs[r[i+1]][r[i]].flows==0){ G.arcs[r[i+1]][r[i]].cost=M; } } } SetTextC1;//白色 //打印C cout< "< Display(G); returntrue; } } voidGraphics: : Display(GraphicsG){//打印各边的流量和容量信息 inti,j; SetTextC2;//绿色 for(i=0;i if(i==0){ cout<<"\t\t"< }else{ cout<<"\t"< } } cout< SetTextC3; for(i=0;i SetTextC2; cout<<"\t"< SetTextC3; for(j=0;j if(G.arcs[i][j].cost==M||G.arcs[i][j].cost==0){ SetTextC6; cout<<"M"<<"\t"; SetTextC3; }else{ cout< } } cout< } SetTextC1; } voidGraphics: : MCMSInfo(GraphicsG,GraphicsG1){//打印最小费用最大流相关信息 inti,j; doublemaxstream=0; doublemincost=0; cout<<"可行流图如下: "< SetTextC2;//绿色 for(i=0;i if(i==0){ cout<<"\t\t"< }else{ cout<<"\t"< } } cout< SetTextC3; for(i=0;i SetTextC2; cout<<"\t"< SetTextC3; for(j=0;j if(G.arcs[i][j].cost<0){ G.arcs[i][j].flows=0; } mincost+=G.arcs[i][j].flows*G1.arcs[i][j].cost; if(G.arcs[i][j].flows==0){ SetTextC6; cout<<"0"<<"\t"; SetTextC3; }else{ cout< } } cout< } cout< SetTextC1; for(j=0;j maxstream=maxstream+G.arcs[0][j].flows; } cout<<"最大流: "; SetTextC5;//紫色 cout< SetTextC1; cout<<"最小费用: "; SetTextC5; cout< SetTextC1; } intmain(){ GraphicsG; SetTextC7; cout<<"//最小费用最大流算法"< cout<<"//顶点从vs开始"< cout<<"//可以求出vs到vt的最小费用最大流"< cout<<"//其中M表示的无穷大"< SetTextC1; G.start(G); return0; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 最小 费用 最大