网络最大流.docx

上传人:b****7 文档编号:8855011 上传时间:2023-02-02 格式:DOCX 页数:15 大小:168.44KB
下载 相关 举报
网络最大流.docx_第1页
第1页 / 共15页
网络最大流.docx_第2页
第2页 / 共15页
网络最大流.docx_第3页
第3页 / 共15页
网络最大流.docx_第4页
第4页 / 共15页
网络最大流.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

网络最大流.docx

《网络最大流.docx》由会员分享,可在线阅读,更多相关《网络最大流.docx(15页珍藏版)》请在冰豆网上搜索。

网络最大流.docx

网络最大流

云南大学数学与统计学实验教学中心

实验报告

课程名称:

运筹学实验

学期:

2012~2013学年第二学期

成绩:

指导教师:

葛瑜

学生姓名:

卢富毓

学生学号:

20101910072

实验名称:

最大流

实验要求:

必做

实验学时:

2学时

实验编号:

07

实验日期:

2013/4/30

完成日期:

2013/5/24

学院:

数学与统计学院

专业:

信息与计算科学

年级:

2010级

一、实验目的

编制程序,在赋权图中找到从发点Vs到收点Vt的最大流,并输出最大流.

二、实验环境

VS2010(C++)

三、实验内容

P272

例14:

用标号法求图10-25所示网络的最大流,弧旁的数是

四、实验过程

A、将上面算法编写实现运行结果如下图:

用标号法寻找网络中最大流的基本思想是寻找可增广链,使网络的流量得以增加,直到最大为止(标号过程进行不下去,而收点vt尚未标号,说明不存在增广路,得到最大流)。

我采用的方法是从零流开始,再用标号法寻求最大流。

标号法主要分为两个步骤:

(1)标号过程

开始标号,初始化结点的结构体数组,然后标记vs为标号点并进行检查,此时其余都是未标号的点。

然后找到与vs有边相连的结点,标记那些点为标号而未检查的点。

取一个标号而未检查(Tag=marking)的点vi,对于一切未标号(Tag=n_mark)的点vj:

A).对于弧(vi,vj),若fij

B).对于弧(vi,vj),若fji>0,则给vj标号(-vi,0),vj点成为标号而未检查的点。

然后找到下一个标号而未检查的点,重复上述步骤,一旦vt被标上号,表明得到一条从vi到vt的增广路径p,转入调整过程。

若所有标号都已检查过去,而标号过程进行不下去时,则算法结束,这时的可行流就是最大流。

(2)调整过程

从vt点开始,通过每个点的第一个标号,反向追踪(根据结点的From信息),可找出增广路P。

直到vs为止。

这时整个增广路径就找到了。

在上述找增广路径的同时计算调整值:

min{min(cij-fij),min(fij)}

a、初始化结果:

输入的结果为红色字体

b、初始化后的到结果:

红框中得到的图的关系与课本例题中的一样!

所以创建图形正确!

c、最后得到的结果:

6x6的矩阵中,每一行中紫色表示的是有边相连的顶点。

其中的两个值,第一个代表的是容量,第二个值代表的是流量。

得到的结果与课本中例题的结果一致。

所以编写的程序正确。

五、实验总结

通过编程来实现的时候,发现手工做的话容易实现,同时在手工做的时候容易忽略一些细节性的东西。

而通过编程来实现的话需要把一些忽略的细节重视起来。

同时有了前面两个实验的铺垫,这个实验实现起来也是得心应手的。

六、源代码

源代码如下:

//图的顶点结构如下:

//-----------------------------------

//|vex|formerNode|flowsDiff|mark|

//-----------------------------------

//图的边的结构如下:

//----------------

//|weight|flows|

//----------------

#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;//流量

};

enumMark{n_mark,marking,h_marked};//分别代表没有标记,已经标记_未检查,已经标记_检查

classVex{//顶点值

public:

stringvexs;//顶点名称

stringformerVex;

doubleflowsDiff;//流量的差值且最小

Markmark;

};

classGraphics{//创建一个图的类

private:

intvexnum;//顶点数

intarcnum;//边数

Vexvexs[Max_vex];//存储定点名称

Arcllarcs[Max_vex][Max_vex];//边数

public:

voidCreateGraphics(Graphics&G);//创建一个图

intLocateIndex(GraphicsG,stringv);//寻找下标

voidMark_getMaxstream(Graphics&G);

boolMark_FindMaxstream(Graphics&G);//标号法寻找最大流

boolMark_Node(Graphics&G,inti);//标记的方法

intCheckMarkNode(Graphics&G,inti);

};

 

//方法实现

//找到相应顶点的下标

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;

doublew,f;//容量、流量

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="";

G.vexs[i].mark=n_mark;

}

SetTextC1;

for(i=0;i

for(j=0;j

G.arcs[i][j].weight=M;

G.arcs[i][j].flows=-1;

}

}

for(k=0;k

cout<<"请输入第"<

";

SetTextC4;

cin>>Vi>>Vj>>w>>f;

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].flows=f;

}

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==M){

SetTextC6;

cout<<"\t"<<"";

SetTextC3;

}else{

cout<<"\t<"<";

}

}

cout<

}

SetTextC1;

cout<

"<

}

//-------------------------标号法寻找最大流-------------------------

voidGraphics:

:

Mark_getMaxstream(Graphics&G){

boolb=true;

inti,j;

G.CreateGraphics(G);//创建图的存储结构

cout<<"-------------------------标号法寻找最大流-------------------------------"<

while(b){

b=Mark_FindMaxstream(G);

if(!

b){

break;

}

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==M){

SetTextC6;

cout<<"\t"<<"";

SetTextC3;

}else{

cout<<"\t<"<";

}

}

cout<

}

SetTextC1;

}

if(!

b){

cout<<"找到了!

最后结果为:

"<

SetTextC2;

for(i=0;i

if(i==0){

cout<<"\t\t"<

}else{

cout<<"\t"<

}

}

cout<

SetTextC3;

for(i=0;i

SetTextC2;

cout<<"\t"<

SetTextC5;

for(j=0;j

if(G.arcs[i][j].weight==M){

SetTextC6;

cout<<"\t"<<"";

SetTextC5;

}else{

cout<<"\t<"<";

}

}

cout<

}

SetTextC1;

}

}

boolGraphics:

:

Mark_FindMaxstream(Graphics&G){

inti,j,k,x;

doubledis;

boolboolean=false;

//step1找到vs,并对与其相连的顶点标记

i=G.LocateIndex(G,"vs");//找到顶点vs

G.vexs[i].flowsDiff=M;

G.vexs[i].mark=h_marked;

boolean=G.Mark_Node(G,i);//标记顶点

if(!

boolean){

cout<<"没有找到增广链"<

returnfalse;

}

//step2从标记的点中找已标记未检查的点

i=0;

j=0;

while(G.vexs[i]pare("vt")!

=0&&G.vexs[i].mark!

=n_mark){//当vt找到且有标记时停止

if(G.vexs[i].mark==marking){

x=0;

G.vexs[i].mark=h_marked;//代表已经检查

G.Mark_Node(G,i);//标记从当前点出发的未标记的点

k=G.CheckMarkNode(G,i);//检查:

已标记未检查的点进行h_marked标记并返回i

if(k==i){

//cout<<"k==i出错"<

for(j=0;j

if(G.vexs[j].mark==marking){

x=x+1;

break;

}

}

if(x==1){

i=x;

}else{

cout<<"k==i出错"<

returnfalse;

}

}else{

i=k;

}

}

if(j==G.vexnum){//找完所有点也不满足条件时停止

i=i+1;

}

j++;

}

//step3路径值调整

i=G.LocateIndex(G,"vt");

dis=G.vexs[i].flowsDiff;//得到vt的流量差

stringforvex;

stringforvex1;

while(G.vexs[i]pare("vs")!

=0){//当顶点为vs时停止

forvex=G.vexs[i].formerVex;

if(forvex.substr(0,1).compare("-")==0){

forvex1=forvex.substr(1,2);

j=G.LocateIndex(G,forvex1);

G.arcs[i][j].flows=G.arcs[i][j].flows-dis;//反向,流量减

}else{

j=G.LocateIndex(G,forvex);//得到前面的顶点的下标

G.arcs[j][i].flows=G.arcs[j][i].flows+dis;//正向,流量加

}

i=j;

}

returntrue;

}

boolGraphics:

:

Mark_Node(Graphics&G,inti){

intj;

doublea,b;

boolb1=false,b2=false;

for(j=0;j

if(G.vexs[j].mark==n_mark){

if(G.arcs[i][j].weight!

=M){//判断是否相连

if(G.arcs[i][j].flows!

=G.arcs[i][j].weight){//正向不是饱和流,标记

G.vexs[j].mark=marking;

G.vexs[j].formerVex=G.vexs[i].vexs;

a=G.vexs[i].flowsDiff;

b=G.arcs[i][j].weight-G.arcs[i][j].flows;

G.vexs[j].flowsDiff=b

b:

a;

b1=true;

}

}

if(G.arcs[j][i].weight!

=M){//判断反向相连

if(G.arcs[j][i].flows!

=0){//判断是否零流,标记

G.vexs[j].mark=marking;

G.vexs[j].formerVex="-"+G.vexs[i].vexs;

a=G.vexs[i].flowsDiff;

b=G.arcs[j][i].flows;

G.vexs[j].flowsDiff=b

b:

a;

b2=true;

}

}

}

}

returnb1||b2;

}

intGraphics:

:

CheckMarkNode(Graphics&G,inti){

intj=0;

for(j=0;j

if(G.arcs[i][j].weight!

=M){//判断是否相连

if(G.vexs[j].mark==marking){//相连,且为marking

returnj;

}

}

if(G.arcs[j][i].weight!

=M){//判断反向相连

if(G.vexs[j].mark==marking){//相连,且为marking

returnj;

}

}

}

returni;

}

intmain(){

GraphicsG;

SetTextC7;

cout<<"//标号寻找最大流算法"<

cout<<"//顶点从vs开始"<

cout<<"//可以求出vs到vt的一条流量最大的路"<

cout<<"//其中M表示的无穷大"<

SetTextC1;

G.Mark_getMaxstream(G);

return0;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1