数据结构与算法学习笔记15:最大流问题 / 二分图 / 有权无权二分图的匹配 / 匈牙利算法 / 银行家算法 / 稳定婚配

引入小题:最短路径

无权图中,如何找到图中点与点之间的最短路径?

  • BFS 广度优先遍历

最大流问题(maximum flow problem)

(前提:有边 有权重)

最大流问题是一种组合最优化问题,指的是如何充分利用装置的能力,使得运输的流量最大以取得最好的效果。

简单算法(可能会失败)

1、构建残量图

2、找一条简单路径,找到路径上的瓶颈值(当前路径所允许流过的最大流量),更新残量图路径权值,并将瓶颈值所在边擦除,重复该操作,直到无简单路径。

在这里插入图片描述

在这里插入图片描述

  • 但实际上,该算法并不一定能够求出最大流,上述图解我们可以看出最大流是2+3=5,但从其他简单路径s→v1→v4→t入手,求解得到的最大流为1+3=4,s→v1→v4→t(不能有更多的水从s流向t,称为阻塞流)。

在这里插入图片描述

  • 最大流是阻塞流,但阻塞流不一定是最大流,上述的4就是该题的一种阻塞流。
福特-富尔克森算法(Ford-Fulkerson)

1、构建残量图

2、找一条简单路径,找到路径上的瓶颈值(当前路径所允许流过的最大流量),更新残量图路径权值,并将瓶颈值所在边擦除。

3、添加反向路径

在这里插入图片描述

时间复杂度

在这里插入图片描述

上例左图为原图,根据原图可容易看出最大流为走s→V1→t和s→V2→t的100+100=200,但在福特-富尔克森算法中,简单路径选择是随意的,如果选择了s→V1→V2→t,则会出现右边的残量图分析过程,后续步骤雷同,共需要200轮才能完成得到最终流量图。若 f f f表示轮, m m m表示边,则其最坏时间复杂度 O ( f ∗ m ) O(f * m) O(fm),依赖于流量的时间复杂度,在流量大的时候很致命,这就是福特-富尔克森算法的弊端。

Edmonds–Karp算法

该算法与福特-富尔克森算法(Ford-Fulkerson)相同,只是定义了找到增广路径时的搜索顺序。找到的路径必须是具有可用容量的最短路径(这可以通过BFS广度优先搜索找到)。

时间复杂度

轮数为m*n,其中m为边数,n为顶点个数,其算法时间复杂度为 O ( m 2 ∗ n ) O(m^2 * n) O(m2n),相较于前面福特-富尔克森算法最坏时间复杂度 O ( f ∗ m ) O(f * m) O(fm)已有很大提升,但实际上,m边数比n顶点个数肯定要大,因此Dinic算法比Edmonds–Karp算法又好一些。

Dinic Algorithm/又称Dinitz算法
层次图概念

层次图,只有上一层到下一层的边,没有同层的边(同层会增加路径的长度),实际上是帮助求最短路径。

在这里插入图片描述

过程分析

1、残量图初始化

2、根据残量图绘制层次图,并根据简单算法寻找阻塞流

3、将阻塞流汇入残量图

4、根据新的残量图更新新的层次图,重复2-4步骤。

在这里插入图片描述

时间复杂度

共需要n-1轮,每轮消耗为m * n,即(n-1)(m * n)

因此其时间复杂度为 O ( m ∗ n 2 ) O(m * n^2) O(mn2),远小于上个Edmonds–Karp算法的 O ( m 2 ∗ n ) O(m^2 * n) O(m2n)

二分图 / 二部图(Bipartite Graph)

顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集,两个子集内的顶点不相邻。即 G = ( u , v , e ) G=(u,v,e) G=(u,v,e),其中u和v内部不可以有边。

在这里插入图片描述

二分图的判定

图上随便找一个点开始遍历,相邻的点为两个部分,全部遍历完看看是否有冲突。

在这里插入图片描述

  • 步骤:1、任选一个点,颜色标记,入队;2、队首元素拿出,找到相关顶点,如未处理过则标记其他颜色,入队,如处理过则看颜色是否冲突,冲突则over。

  • 如果是非连通图,那就结束后再选一个点进行标记,重复上述步骤,直到再也找不到未被标记的点为止。

  • 实际就是BFS的操作~

匹配概念

匹配指的就是边的集合,但注意其限制,集合内的边顶点是不可以相同的。

如下图中男1女1,男2女3,男3女1(此时女1就相同重复),因此这一组就不是匹配。

最大匹配的概念就是所有匹配中边的数量最大

在这里插入图片描述

无权二部图中的最大匹配问题

MCBM: 无权二部图中的最大匹配问题 Maximum-Cardinality Bipartite Matching (MCBM)

  • 实际上该类题用最大流就可解决,前后分别加S和T,所有权值均赋值为1,使用前文算法最终即可得到匹配方案。但注意,最大流的方法只适用于无权图的最大匹配求解,有权图是不可用这个来求最大匹配的。

在这里插入图片描述

有权二部图中的最大匹配问题
核心方法

1、将权重符号取反

2、找最小匹配(实际上就是所求的最大匹配)

匈牙利算法(找最小匹配)

要求uv中顶点个数相同,如果不相同可以补全(把边的权值设置为无穷大),时间复杂度为 O ( n 3 ) O(n^3) O(n3)

步骤分析:

在这里插入图片描述

1、根据关系图绘制邻接矩阵;

2、找到每行内的min,然后该行所有元素减去min值;

3、找到每列内的min,然后该列所有元素减去min值;

4、画线;

  • 以最少线覆盖0;(只能画横线or竖线,不能斜!)

  • 判断操作是否结束(若线的条数 = 顶点个数 则结束,否则继续);

  • 没结束则找到未被线覆盖区域的min,然后未覆盖区域的所有元素减去min值;

  • 线覆盖的交叉点位置加上min值,重复第4步操作……直到线的条数 = 顶点个数 结束。

5、最小匹配;

  • 将所有0对应的边重新构建关系图画出

  • 找到一行中只有一个0的点,以其为基础,将冲突的点进行删除,直到匹配关系成立(无重复顶点)。

6、权值累加计算。

稳定婚配

没有人可以找到比当前更好的配偶

Gale-Shapley 算法

时间复杂度为 O ( n 2 ) O(n^2) O(n2)

  • 流程分析:

    所有人向第一顺位喜欢的人求婚

    • 此时被求婚的人如果未婚,且仅有一人向其求婚,则牵手成功
    • 此时被求婚的人如果未婚,且有多人向其求婚,则根据自己的排名进行顺位,选追求者中最喜欢的结婚
    • 此时被求婚的人如果已婚,看追求者和现配偶间更喜欢谁,相应完成拒绝追求者或与配偶离婚的操作

银行家算法

一种最有代表性的避免死锁的算法

应用前提条件

1、固定数量的进程共享固定数量的资源;

2、每个进程要预先指定完成工作所需的最大资源数量;

3、每个进程不能申请比系统可用资源总数还多的资源;

4、每个进程等待资源的时间是有限的;

5、如果系统满足了进程对资源的最大需求,那么进程应该在有限时间内使用资源然后归还给系统。

算法分析

1、需要存储可分配的资源数量 A A A

2、需要知道当前进程已得到的资源 B B B

3、需要知道当前进程所需的最大资源数量 C C C

4、需要知道进程还需要的资源 D D D

5、需要知道每一次的需求 E E E

当某一个进程提出资源申请时(E):

1、 E ≤ D E≤D ED,否则直接报错

2、 E ≤ A E≤A EA,否则需要等待

3、满足2的条件(系统给了),更新系统各个部分的资源: A = A − E ; B = B + E ; D = D − E A=A-E;B=B+E;D=D-E A=AEB=B+ED=DE

​ 检测系统安全性:① 看标记(是否被检查过);② 如果没被检查,则检查,看是否满足 D < F D<F DF,满足的话则进行分配,更新 F F F,然后进行标记(已检查),如果不满足,那么需要把状态恢复(把前面步骤中: A = A − E A=A-E A=AE B = B + E B=B+E B=B+E D = D − E D=D-E D=DE全部恢复成更新前的样子,然后进行下一次重新分配)。( F F F为目前可用资源数量,其实和上述的 A A A差不多,但 A A A F F F也有一些区别, F F F是检查的时候用的,各个进程都需要进行安全性检查,给一号进程检查完检查二号的时候, F F F就不是一号的 F F F了,是被更新过减去一号分配后的…以此类推。)

Bitmap算法

Bitmap算法是用bit数组来记录0-1两种状态,然后再将具体数据映射到这个比特数组的具体位置,这个比特位设置成0表示数据不存在,设置成1表示数据存在。Bitmap算法和布隆过滤器主要解决大数据去重的问题。用于对大量整型数据做去重和查询。

学习链接:数据结构与算法必知— Bitmap位图与布隆过滤器 - 简书 (jianshu.com)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
算法数据结构涵盖了以下主要内容: 数据结构(Data Structures): 逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法算法设计:研究如何将决问题的步骤形式化为一系列指令,使得计算机可以执行以求问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法数据结构不仅有助于理程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法算法设计:研究如何将决问题的步骤形式化为一系列指令,使得计算机可以执行以求问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法数据结构不仅有助于理程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法算法设计:研究如何将决问题的步骤形式化为一系列指令,使得计算机可以执行以求问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法数据结构不仅有助于理程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

97Marcus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值