算法分析报告与复杂性理论 实验报告材料 最大流问题Word格式文档下载.docx
- 文档编号:20230190
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:12
- 大小:781.35KB
算法分析报告与复杂性理论 实验报告材料 最大流问题Word格式文档下载.docx
《算法分析报告与复杂性理论 实验报告材料 最大流问题Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《算法分析报告与复杂性理论 实验报告材料 最大流问题Word格式文档下载.docx(12页珍藏版)》请在冰豆网上搜索。
教务处制
一.实验目的与实验内容
实验目的:
(1)
掌握最短增益路径法思想。
(2)
学会最大流问题求解方法。
实验内容:
1.给定下面的通信网络,该网络中各节点之间的路径流量给定,使用最短增益路径法求解该网络的最大流量,并进行流量分配。
2.
要求用加权矩阵输入该网络,输出每次迭代过程中的最大流量及各路径分配的流量。
3.
如果能利用图形界面输出动态求解过程(在网络结构的图形显示中,标注每一次求得的增益路径,并显示当前流量分配),可获加分。
算法思想提示:
1.
利用二维数组C[i,j]和F[i,j]分别存放容量和流量。
构建队列类Queue,该类具有取队首元素,加入队尾元素等方法。
具体算法过程参见教材pp.271-272
二.实验步骤
最大流问题的问题描述:
如上图。
s是源点,t为汇点,每条边上数字的含义是边能够允许流过的最大流量。
可以将边看成管道,3代表该管道每秒最多能通过3个单位的流量。
最大流问题即是说,从s点到t点,最大允许流量是多少?
最大流问题的算法思想:
最短增益路径法(先标记先扫描算法):
用两个记号来标记一个新的顶点
第一个标记指出从源点到被标记顶点还能增加多少流量
第二个标记指出另一个顶点的名字,可加上+或-来表示顶点时通过前向边还是后向边访问到的
算法及其伪代码:
Maxflow(G)
//最短增量路径算法的实现
//输入:
网络G,具有一个源点1和一个汇点n,每条边(i,j)的容量都是正整数Uij
//输出:
最大流量x
//对网络中的每条边(i,j),设xij=0
//把源点标记为∞,-,再把源点加入到空队列Q中
WhilenotEmpty(Q)do
i←Front(Q);
Dequeue(Q)
for从i到j的每条边do//前向边
ifj没有被标记
rij←uij-xij
ifrij>
0
Ljmin{Li,xji};
用L,i-来标记j
Enqueue(Q,j)
If汇点被标记了
//沿着找到的增益路径进行增量
j←n//从汇点开始,用第二个标记反向移动
whilej!
=i//没有到达源点
if顶点j的第二个标记是i+
xij←xij+Ln
else//顶点j的第二个标记是i-
xji←xji-Ln
j←i;
i←i的第二个标记指出的顶点
除了源点,擦去所有顶点的标记
用源点对Q重新初始化
returnx//当前流量是最大的
思路以及代码解释:
(全部源代码见附件)
先创建一个解决问题的类,命名为G。
计算最大流作为这个类中的一个方法来实现。
利用二维数组Map[i,j]和Flow[i,j]分别存放容量和流量。
添加头文件#include<
queue>
,后面需要用到队列,需要该类的取队首元素,加入队尾元素等方法。
classG
{
public:
G();
G(intn,intstart,intend);
voidEdge(inta,intb,intflow);
//顶点a和顶点b之间的流量
voidMaxflow();
//计算最大流
private:
intN;
//顶点个数
intStart;
//源点
intEnd,//汇点
**Map,//网络容量
**Flow,//通过流量
**Rest,//剩余流量
*Pre,//标记流向,正为前向,负为后向
*Sign,//顶点是否标记,0为未标记,1为已标记
*P;
//过程变量,记录流量
boolSignN();
//标记顶点
intMin(inta,intb);
//计算最小值
voidUpdate();
//更新网络
};
构造函数就先定义两个
G:
:
G(){Pre=NULL;
}//不带参数的构造函数
G(intn,intstart,intend)//带三个参数的构造函数,顶点个数,源点和汇点
{初始化}
在类G中,实现了voidMaxflow();
方法,用来计算最大流,
其中标记顶点的函数定义为boolSignN();
boolG:
SignN()//标记顶点
Update();
//更新
queue<
int>
que;
//创建一个队列的对象
que.push(Start);
//把源点放进队列里面
Sign[Start]=1;
//将源点标记
P[Start]=1000;
Pre[Start]=-1;
//标记流向为后向
while(!
que.empty())//WhilenotEmpty(Q)do
{
inthead=que.front();
//不断地取队首为head
que.pop();
for(inti=1;
i<
=N;
i++)
{
//如果为标记顶点j是由j到i的有向边和遍历队列中的前面顶点i相连接的,而且j具有大于0的未使用容量rij=uij-xij,其中uij为边的总容量,xij为当前正容量,那么顶点j就标记为lj,i+,其中lj=min{li,rij}
if(Rest[head][i]>
0&
&
Sign[i]==0)//如果从head出发到其它顶点,有剩余流量大于0,并且没有被标记
{
P[i]=Min(P[head],Rest[head][i]);
Pre[i]=head;
Sign[i]=1;
if(i==End)returntrue;
//当扫描到汇点后返回
que.push(i);
}
}
for(i=1;
//如果为标记顶点j是由j到i的有向边和遍历队列中的前面顶点i相连接的,而且j具有大于0的未使用容量xji,那么顶点j就标记为lj,i-,其中lj=min{li,xji}
if(Flow[i][head]>
Sign[i]==0)//如果有顶点到head的流量大于0.并且没有被标记
P[i]=Min(P[head],Flow[i][head]);
Pre[i]=-head;
}
}
returnfalse;
}
voidG:
Maxflow()//计算最大流
intmaxflow=0;
while(SignN())//迭代地去标记顶点
maxflow=maxflow+P[End];
for(inti=End;
i>
1;
i=abs(Pre[i]))
if(Pre[i]>
0)//流向为前向
{
Flow[Pre[i]][i]=Flow[Pre[i]][i]+P[End];
if(Pre[i]<
0)//流向为后向
Flow[i][abs(Pre[i])]=Flow[i][abs(Pre[i])]-P[End];
cout<
<
"
最大流:
maxflow<
endl;
//输出最大流量
三.实验结果与分析
编写主函数,对于下图的程序运行结果
以上就是每次迭代的过程,下面详细解释一下这些过程。
1—>
2—>
3—>
6,一条4的通路。
此时流量为4
此时流量为6。
此时流量为8。
此时流量为10
下一次迭代之后,流量没有增长,那么结束。
最后的结果应该是这样的。
最大流量为10
由最大流最小割定理可以验证。
该图的最小割为(2,5)(3,6)(4,5),最小割流量为2+4+4=10。
因为网络中的最大流量值等于它最小割的容量,可以验证上图的正确性。
后面,我也实现了用加权矩阵输入该网络,输出每次迭代过程中的最大流量及各路径分配的流量。
四.实验心得
在现实生活中,在实际的网络中,网络的结点和边都是有容量限制的.很多情况下我们需要知道在一个有容量限制的网络中两个指定结点(分别称为源点和汇点)之间最多能传输多少流量,并确定达到这个最大流量的传输策略.网络最大流问题(简称最大流问题)就是描述这个问题的数学模型.
求解最大流的算法有不少,在此次实验中,我学习到了最短增益路径法,也明白了,最大流量值和最小割容量是相等的。
本次实验挺有难度的,让我明白了最大流问题的算法,对迭代改进算法的认识也更加深刻了。
这次实验结束后让我感觉到好的算法是多么的重要,当然合理利用算法也是不可忽视的。
这次实验虽然花了很大精力,却收获累累。
指导教师批阅意见:
成绩评定:
指导教师签字:
年月日
备注:
注:
1、报告内的项目或内容设置,可根据实际情况加以调整和补充。
2、教师批改学生实验报告时间应在学生提交实验报告时间后10日内。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法分析报告与复杂性理论 实验报告材料 最大流问题 算法 分析 报告 复杂性 理论 实验 材料 最大 问题