1、深 圳 大 学 实 验 报 告课程名称: 算法分析与复杂性理论 实验名称: 实验五 最短增益路径法求最大流问题 学院: 计算机与软件学院 专业: 软件工程 报告人: 文成 学号: 2150230509 班级: 学术型同组人: 无 指导教师: 杨烜 实验时间: 2015/11/232015/11/30 实验报告提交时间: 2015/11/28 教务处制一 实验目的与实验内容实验目的:(1) 掌握最短增益路径法思想。(2) 学会最大流问题求解方法。实验内容:1. 给定下面的通信网络,该网络中各节点之间的路径流量给定,使用最短增益路径法求解该网络的最大流量,并进行流量分配。2. 要求用加权矩阵输入该
2、网络,输出每次迭代过程中的最大流量及各路径分配的流量。3. 如果能利用图形界面输出动态求解过程(在网络结构的图形显示中,标注每一次求得的增益路径,并显示当前流量分配),可获加分。算法思想提示:1. 利用二维数组 Ci,j和 Fi,j分别存放容量和流量。2. 构建队列类 Queue,该类具有取队首元素,加入队尾元素等方法。3. 具体算法过程参见教材 pp.271-272二实验步骤最大流问题的问题描述:如上图。s 是源点,t 为汇点,每条边上数字的含义是边能够允许流过的最大流量。可以将边看成管道,3 代表该管道每秒最多能通过 3 个单位的流量。最大流问题即是说,从 s 点到 t 点,最大允许流量是
3、多少?最大流问题的算法思想:最短增益路径法(先标记先扫描算法):用两个记号来标记一个新的顶点第一个标记指出从源点到被标记顶点还能增加多少流量第二个标记指出另一个顶点的名字,可加上+或-来表示顶点时通过前向边还是后向边访问到的算法及其伪代码:Maxflow (G)/最短增量路径算法的实现/输入:网络 G,具有一个源点 1 和一个汇点 n,每条边(i,j)的容量都是正整数 Uij/输出:最大流量 x/对网络中的每条边(i,j) ,设 xij=0/把源点标记为,-,再把源点加入到空队列 Q 中While not Empty(Q) doiFront(Q);Dequeue(Q)for 从 i 到 j 的
4、每条边 do/前向边if j 没有被标记rij uij - xijif rij 0Lj minLi,xji;用 L,i-来标记 jEnqueue(Q,j)If 汇点被标记了/沿着找到的增益路径进行增量jn/从汇点开始,用第二个标记反向移动while j!=i/没有到达源点if 顶点 j 的第二个标记是 i+xijxij+Lnelse/顶点 j 的第二个标记是 i-xjixji-Lnji;ii 的第二个标记指出的顶点除了源点,擦去所有顶点的标记用源点对 Q 重新初始化return x/当前流量是最大的思路以及代码解释:(全部源代码见附件)先创建一个解决问题的类,命名为 G。计算最大流作为这个类中
5、的一个方法来实现。利用二维数组 Mapi,j和 Flowi,j分别存放容量和流量。添加头文件#include ,后面需要用到队列,需要该类的取队首元素,加入队尾元素等方法。class Gpublic:G();G(int n,int start,int end);void Edge(int a,int b,int flow); /顶点 a 和顶点 b 之间的流量void Maxflow(); /计算最大流private:int N; /顶点个数int Start; /源点int End, /汇点*Map, /网络容量*Flow, /通过流量*Rest, /剩余流量*Pre, /标记流向,正为前向
6、,负为后向*Sign, /顶点是否标记,0 为未标记,1 为已标记*P; /过程变量,记录流量bool SignN(); /标记顶点int Min(int a,int b); /计算最小值void Update(); /更新网络;构造函数就先定义两个G:G() Pre=NULL; /不带参数的构造函数G:G(int n,int start,int end) /带三个参数的构造函数,顶点个数,源点和汇点初始化在类 G 中,实现了 void Maxflow();方法,用来计算最大流,其中标记顶点的函数定义为 bool SignN();bool G:SignN()/标记顶点Update();/更新q
7、ueue que;/创建一个队列的对象que.push(Start);/把源点放进队列里面SignStart=1;/将源点标记PStart=1000;PreStart=-1;/标记流向为后向while(!que.empty()/While not Empty(Q) doint head=que.front();/不断地取队首为 headque.pop();for(int i=1;i0 Prei=head;Signi=1;if(i=End) return true;/当扫描到汇点后返回que.push(i);for(i=1;i0 Prei=-head;Signi=1;if(i=End) retu
8、rn true;/当扫描到汇点后返回que.push(i); return false;void G:Maxflow()/计算最大流int maxflow=0;while(SignN()/迭代地去标记顶点maxflow=maxflow+PEnd;for(int i=End;i1;i=abs(Prei)if(Prei0)/流向为前向FlowPreii=FlowPreii+PEnd;if(Prei236,一条 4 的通路。此时流量为 4此时流量为 6。此时流量为 8。此时流量为 10下一次迭代之后,流量没有增长,那么结束。最后的结果应该是这样的。最大流量为 10由最大流最小割定理可以验证。该图的最
9、小割为(2,5) (3,6) (4,5),最小割流量为 2+4+4=10。因为网络中的最大流量值等于它最小割的容量,可以验证上图的正确性。后面,我也实现了用加权矩阵输入该网络,输出每次迭代过程中的最大流量及各路径分配的流量。四 实验心得在现实生活中,在实际的网络中,网络的结点和边都是有容量限制的. 很多情况下我们需要知道在一个有容量限制的网络中两个指定结点(分别称为源点和汇点)之间最多能传输多少流量,并确定达到这个最大流量的传输策略. 网络最大流问题(简称最大流问题)就是描述这个问题的数学模型.求解最大流的算法有不少,在此次实验中,我学习到了最短增益路径法,也明白了,最大流量值和最小割容量是相等的。本次实验挺有难度的,让我明白了最大流问题的算法,对迭代改进算法的认识也更加深刻了。这次实验结束后让我感觉到好的算法是多么的重要,当然合理利用算法也是不可忽视的。这次实验虽然花了很大精力,却收获累累。指导教师批阅意见:成绩评定:指导教师签字:年 月 日备注:注:1、报告内的项目或内容设置,可根据实际情况加以调整和补充。2、教师批改学生实验报告时间应在学生提交实验报告时间后 10 日内。