算法设计与分析(实验6)---最短增益路径法求解最大流问题

一.实验目的

  1. 掌握最大流算法思想。
  2. 学会用最大流算法求解应用问题。

二.实验步骤与结果

1.上述问题可按最大流问题求解:

假设有医生n个,现要安排元旦(共D’天)和五一(共D’’天)的排班,医生1的可安排日期为{元旦第1、2天;五一第1、D’’天},医生2的可安排日期为{元旦第2、D’天;五一第1、2天},医生n的可安排日期为{元旦第2天;五一第2、D’’天}。

图构建如下:

 

且该图满足实验的三个限制:

①每一个假日都有医生值班

②每人每个假期最多值班一天

③每个医生值班不得超过c日

        则将排班问题转化为了最大流问题:如果求解最大流的结果等于总的假日天数,那么存在分配方案,否则无解。查看增广图每条边的权值,可以确定最终选择的是那些路径(即分配方案)。

        求解最大流的方法:

(1)Ford-Fulkerson方法

①算法概述

在Ford-Fulkerson方法的每次迭代中,找出任意增广路径p,沿p每条边的流f加上其残留容量。 

    求最大流即找到一种符合个点流量限制的、多条不交叉的从s到t的路径,使最终获得的流量最大。可以通过dfs深度优先搜索获得从s到t的路径,但如果要获得符合条件的最优路径组合,用Ford-Fulkerson算法来判断每次获得路径是否是组合里的。

    对于每次获得的路径(增广路径),我们可以将该路径反向(由原流网络变为残留网络),看是否能与剩余量形成连通路径(根据当前获得的残留容量)。如果有需要减去改变,重复操作,模拟纠错过程。最后完全没有连通路径时即计算完毕。

②伪代码

Ford-Fulkerson(G,s,t)

for each(u,v)∈E(G)

    do f[u,v]←0

        f[v,u]←0

while there exists a path p from s to t in the residual network Gf

    do cf(p) ←min{cf(u,v):(u,v)is in p}

    for each (u,v) in p

       do f[u,v]←f[u,v]+cf(p)

           f[v,u]← -f[u,v]   

  

(2)Edmonds-karp算法

①伪代码

Edmonds-karp算法伪代码:

while true

通过bfs()找到增广路径p

if p不存在

break;

for 边e in p

更新e的权值

②算法步骤:

(1)从源点开始,用BFS找一条最短的增广路径,计算该路径上的残量最小值,累加到最大流值;

(2)沿着该路径修改流量值,实际是修改是残量网络的边权;

(3)重复上述步骤,直到找不到增广路时,此时得到的流就是最大流。

③正确性测试:

输入(2,2 , 2 , 1)

(即:医生数目=2、假期数目=2、每个假期的假日数目=2、每个医生的最多值班天数c=1)

④算法效率: 

 

3)Dinic算法

①算法概述:

首先对图进行BFS分层,搜索增广路径使用DFS搜索,使得一次搜索可以更新多条增广路上的权值,从而提高速度。

②伪代码

Dinic_func():

dfs(x,minval):    //x为点序号,minval为到达点x的(最小)流

    if x==t:    //到达汇聚节点t返回

    Return paths

for y in x.adj:    //遍历x的下一邻点,进行整一层的更新

    renew(minval)    //更新邻点边加入后(最小)流

    res=dfs(y,minval):

    if res:

        reweight(edge(x,y))

        return res

return 0

while bfs():

    while dfs()

③算法效率:时间复杂度O(VE2) 

(4)引入当前弧优化:

        由于dfs一旦找到就返回,而一次bfs分层可能存在很多条相同长度的增广路,那么会在同一张图上跑多次dfs,而图不断更新,可用的边越来越少,我们试图跳过前面已经走过的“死路”,直接从未访问的路开始走。

        在Dinic+弧优化算法下,因为一共e条边,而不管做多少次dfs,因为减少了对死路的判断,保证每次邻接表第一个邻居就是能走的活路,所以每次dfs走n步一定能够走到目标而不必回退,dfs的开销由O(e)变为O(n),而因为最多有e条路径,dfs需要最多做e次,所以每一轮的代价是O(ne),而因为外循环的bfs分层最多进行n次,所以总的代价是O(n2e)。 

DFS_hu(x,flow):

      if x==s //汇点

              return flow

      for i=cur[x] to x的最后一条弧

             y=i指向的点

             fxy=边xy的权值

             r=dfs(y,min(flow,fxy))

             if r!=0

                    更新边xy的权值

                    return r

       return 0

5)引入多路增广策略:

如下图所示,普通dinic算法找到之后,直接全部退出,而多路增广优化的Dinuc算法找到之后,回溯到父节点,然后继续向下搜索,最后退栈的时候再更新边的权值,这样一次dfs可以进行多次更新。

 

 伪代码:

DFS_add2(x,flow):

      if x==s //汇点

              return flow

      temp =flow

      for y in 邻接[x]

             fxy=边xy的权值

             r=dfs(y,min(flow,fxy))

             if r!=0

                    更新边xy的权值

                    flow-= r

             if flow=0

                    return temp

       return temp-flow

(6)ISAP

ISAP在dfs的同时就动态地更新节点的层次关系,减少bfs的次数,将dfs利用到极致。ISAP算法只需要一次bfs建立最初的层次关系。除此之外,ISAP算法还引入了“gap”优化,即如果某一高度的节点数目为0,直接判断没有路径并且结束搜索。因为按层次bfs保证层次是严格连续下降的,如果某一高度节点数目为0表示出现断层,无法到达。

DFS_ISAP(x,flow):

      if x==s //汇点

              return flow

      temp =flow

      for y in 邻接[x]

             fxy=边xy的权值

             r=dfs(y,min(flow,fxy))

             if r!=0

                    更新边xy的权值

                    flow-= r

             if flow=0

                    return temp

       gap[level[x]]--

       level[x]++  //调整高度

       gap[level[x]]++

       return temp-flow

时间复杂度分析:

该算法不带访问控制数组,一个节点会被多次访问,最多有e条增广路径,而每次需要走过n个点到达汇点,所以复杂度O(ne),因为外循环需要判断源点的高度,而源点最多增高n次,总体复杂度为O(n2e)

2.算法对比:

         由数据及绘图对比可明显看出,Dinic算法具有很好的优化效果,且适用在各种规模的数据集上。

3.控制变量分析:

由实验数据结果可以得出以下结论:

        改变医生数目和假期数目和节假日数目算法测试运行时间随着参数数值规模增大呈现明显增加变化,但是最大值班天数对运行时间影响不大。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/599234.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT基础(一) GPT的前世今生

文章目录 GPT模型简史GPT系列模型ChatGPT的应用 最近ChatGPT3.5可以免注册使用了,出来刨一波坟 说一说ChatGPT的来源和应用。 GPT模型简史 Generative pre-trained transformers(GPT)生成式预训练转换模型是大语言模型的一种(Large Language Model–>LLM)。它是…

如何在 Windows 上安装 Jupyter Notebook?

Jupyter Notebook 是一个开源 Web 应用程序,可用于创建和共享包含实时代码、公式、可视化效果和叙述文本的文档。用途包括数据清理和转换、数值模拟、统计建模、数据可视化、机器学习等 在本文中,我们将看到使用 pip 安装在Windows上安装 Jupyter Noteb…

Java8关于Function接口

Java学习-Function接口 1 函数式接口简介和学习地址2 两种常见的函数式接口2.1 Runnable:执行接口,不接收参数,也无返回结果。2.2 Consumer:作为消费接口,接收一个参数,无返回结果。 3 初识3.1 定义Functio…

系统架构评估_2.SAAM方法

SAAM(Scenarios-based Architecture Analysis Method)是卡耐基梅隆大学软件工程研究所(SEI at CMU)的Kazman等人于1983年提出的一种非功能质量属性的架构分析方法,是最早形成文档并得到广泛使用的软件架构分析方法。最…

MySQL基础练习题:创建数据库

这部分主要是为了帮助大家回忆回忆MySQL的基本语法,数据库来自于MySQL的官方简化版,题目也是网上非常流行的35题。这些基础习题基本可以涵盖面试中需要现场写SQL的问题。 创建数据库 在开始练习之前,我默认你的电脑上是没有本系列练习题需要…

物联网可视化平台

随着数字化转型的深入,物联网技术正在成为企业实现智能化、高效化运营的重要工具。物联网可视化平台,作为连接物理世界与数字世界的桥梁,为企业提供了直观、实时的数据展示和监控能力,从而在数字化转型中扮演着关键角色。 一、物…

内外网数据交换发展进程:安全与便捷并行

随着信息化的不断推进,医院、党政以及企业的内外网数据交换正成为日益关注的焦点。在保障数据安全的前提下,需要寻求一种既安全可靠又操作便捷的数据传输方式。本文将探讨内外网数据交换发展进程,分析各种传输方式的优缺点,以及它…

HG-SL:基于全局和局部用户行为的新闻

一、概述 本文的主要目标是,仅通过用户行为来判断新闻的真伪。其之所以抛弃传统的基于视频内容、用户反馈(点赞和评论)等信息,是认为,这些内容很容易存在造假的情况(即有水军机器人操控)。而基于…

css anminate 加载中三个点点动态出现

期待效果&#xff1a; 核心代码&#xff1a; css3 anminate方法 //html <div>加载中<span id"dot">...</span></div>//css <style>   #dot {display: inline-block;width: 1.5em;vertical-align: bottom;overflow: hidden;animati…

Linux初学(十七)redis

一、简介 redis就是一个内存数据库 redis中的数据&#xff0c;都是保存在内存中 端口&#xff1a;6379 二、安装redis 方法一&#xff1a;编译安装 方法二&#xff1a;yum安装-epel 第一步&#xff1a;配置epel源 详见&#xff1a;http://t.csdnimg.cn/AFl1K第二步&#xff1a…

【pycharm报错】rror: Microsoft Visual C++ 14.0 or greater is required.

一、报错 二、下载vs 路径&#xff1a;https://visualstudio.microsoft.com/zh-hans/visual-cpp-build-tools/ 三、安装 四、安装成功并启动 重新安装chromadb成功

MTK i500p AIoT解决方案

一、方案概述 i500p是一款强大而高效的AIoT平台&#xff0c;专为便携式、家用或商用物联网应用而设计&#xff0c;这些应用通常需要大量的边缘计算&#xff0c;需要强大的多媒体功能和多任务操作系统。该平台集成了Arm Cortex-A73 和 Cortex-A53 的四核集群&#xff0c;工作频…