FDS晓风残月记略 | AOE网络与网络流&&哈希算法
可能大概是最后一篇自学FDS的笔记了, 解决最后两个问题
残月: 古人对十二月的雅称, 在此表示最后几篇文章
前言
大纲
- AOE网络与网络流
- 哈希算法
参考资料
正文-上
AOE网络
AOE(activity on edge)网络是一张有向带权图, 其中有向边代表活动, 权值代表活动持续的时间.
关键路径
一个AOE网络有且仅有一个入度为0的节点, 我们称之为源点S; 以及一个出度为0的节点, 我们称之为汇点T. 我们将源点的时间戳记作0.
节点是一个时间概念, 表示两项活动之间的间隔, 这个间隔有长有短. 对于任意一个节点(S,T除外), 当且仅当进入节点的活动全部完成, 离开节点的活动才能开始.
为了保证工期的按时完成, 我们要保证那些绝对不能拖延的活动按时完成, 由这些活动构成的路径, 我们称为关键路径.
节点的时间
对于任何一个节点, 我们存在一个最早发生时间EHT[]
和最晚发生时间LHT[]
.
- 最早发生时间: 指对于节点V来说, 所有他的前提节点U都完成的时间点. 因为只有所有前提节点U都完成时, 节点V才能发生, 递推公式可写作
EHT[V] = 0
(当V为源点S)EHT[V] = max{ EHT[U] + <U,V> }
(当V不是源点S, 其中U为任意前提节点)
- 最晚发生时间: 指对于节点V来说, 能不使后继节点W的最晚发生时间延长的最晚时间. 听着可能有点绕, 举个例子, W有前提节点V1和V2, 假设V1和V2有相同的最早发生时间, <V1,W>=30, <V2,W>=100, 那么, 只要我们在V1节点磨蹭的时间x<=70, W都可以在t=100的时候发生, 这时我们说V1的最晚发生时间是70. 递推公式可写作
LHT[V] = LHT[V]
(当V为汇点T, 我们认为其最早发生时间就是工期)LHT[V] = min{ LHT[W] - <V,W> }
(当V不是汇点T, 其中W为任意后继节点)
边的时间
知道了任意节点的最早发生时间和最晚发生时间, 我们可以对边的时间要求做出更详细的描述.
对于<V,W>, 存在松弛时间ST = LHT[W] - EHT[V] -<V,W>
. 松弛时间表示能在该边延误的最长时间. 假如存在松弛时间为0的边构成的一条路径, 则该路径是关键路径.
AOV网络
AOV(activity on vertex)网络与AOE网络相对, 是将节点作为活动. 对于求解有关AOV网络的问题, 我们一般使用拓扑排序.
拓扑序: 如果在AOV网络中, 存在路径V->W, 则相应的排序中V也在W前面, 则这样的排序结果我们称为拓扑序.
- 一个AOV网络的拓扑序不一定是唯一的.
- 一个AOV网络如果有拓扑序, 则一定是一个DAG(有向无环图).
拓扑排序
拓扑排序的思路就是, 每次取出入度为0的节点(因为入度为0的节点没有了前驱, 一定是能发生的)入队, 并在出队时调整该节点后驱的入度. 伪代码描述如下
auto toposort(Graph G){ |
网络流
类似于水流, 我们可以定义网络图中的流量.
对于给定有向图G, 定义唯一的源点S和唯一的汇点T, S和T的定义均和AOV,AOE的定义相似, 不同的是, 网络流中每条边<U,V>均有一个最大容量c(U,V). 我们将上述网络流记作G(V,E,c).
可行流
对于G(V,E,C), 若给每条边<U,V>给定一个流量f(U,V), 使0<=f(U,V)<=c(U,V)
对于任意一条边均为true
, 且满足以下条件:
- S的流出量 = 网络的流量和 = T的汇入量
- 对任意节点均有: 汇入量之和 = 流出量之和
对于满足以上条件的f(U,V)的集合, 我们称之为可行流.
注意: f(U,V)既不能大于c(U,V), 也不能小于0(即出现负流量的情况).
例如, 对于下列网络流
就有多种可行流, 我们选取其中两种
最大流
在所有可行流中, 我们关注流量最大流–最大流.
在最大流问题中, 流量f和容量c满足以下条件:
建立残差图
为了求解最大流, 我们需要建立一个残差图, 用来描述每条边的富余容量.
将残差容量,源点S和汇点T组合在一起的新图称为残差图, 记作
EK增广路算法
在残差图中, 路径S->T即为增广路.
增广路的流量即是路径上最小残差.
EK算法即是利用增广路不断更新最大流量, 直到不存在增广路为止.
实现思路如下:
- 利用BFS寻找并记录一条增广路, 记下增广路的流量(路径上最小边权)
- 更新增广路的边权(正向边减去流量, 反向边加上流量)
- 重复上述过程, 直到找不到增广路为止
反向边: 在BFS的过程中, 我们无法保证能搜索到所有增广路, 因此我们需要一次反悔的机会. 反向边提供了这样的机会. 当正向边的流量增大时, 反向边的流量减少, 反之亦然. 这样, 当我们两次分别从两个方向经过某一条边, 我们增广的值就能相互抵消, 达到重复遍历的效果.
模板题AC代码如下
|
后记
哈希的东西比较杂乱, 感觉自学的意义和价值不大, 留个坑吧(逃