代码链接:深大算法实验六——最大流问题-C++文档类资源-CSDN下载
目录
一. 问题描述
1. 有m篇论文和n个评审,每篇论文需要安排a个评审,每个评审最多评b篇论文。请设计一个论文分配方案。
2. 要求应用最大流解决上述问题,画出m=10,n=3的流网络图并解释说明流网络图与论文评审问题的关系。
3. 编程实现所设计算法,计算a和b取不同值情况下的分配方案,如果没有可行方案则输出无解。
二. 构建流网络
我们可以将问题抽象成每一个评审和论文是一个节点,将每个评审最多评的论文数量作为评审的入度,也就是说评审节点最多承载b单位的流,每个论文需要多少评审作为论文节点的出度,也就是说每篇论文需要a单位的流。再加上首位两端的起点和汇点即可生成流网络。
中间的蓝色边的权值全部为1,代表每个评审都可以选择所有的论文。
三. 求解过程
将使用FF方法来寻找此流网络的最大流。若最大流可以等于说明存在分配方案,若小于
则说明还有论文没有被批完,则没有存在可行的分配方案。在进行寻找最大流时进行寻找分配方案。
由于在用FF方法时需要使用DFS进行查找最短增广路径,在查找时若遇到评委节点指向论文节点的化,就记录下其边。
四. Ford-Fulkerson方法
F-F方法是一种解决最大流的一种方法,之所以称之为方法而不是算法是因为其实现算法有很多种。
F-F方法的最重要的三个思想是:残留网络、增广路径和割。
F-F方法的过程是:
-
-
- 找到一条增广路径
- 求出这条路径的最大流(即看这条路径的最小权值)
- 更新权值并起来画出其残留网络
- 在残留网络中继续寻找增广路径
- 重复1、2、3、4直到没有增广路径到汇点
-
F-F方法的基本伪代码:
Ford-Fulkerson方法(G,s,t)
初始化流f为0
While(存在一条增广路径p) {
沿着增广路径p增广流f
}
返回f
1. 残留网络
残留网络是更新权值时,增加一条反向边,反向边的值即为通过该边的流的大小。
如上图,该边的值为14,通过的流大小是11,更新权值后并且更新成残留网络后,反向边权值为11,正向边为3。
2. 割
割是可以将流网络分解成两个区域,每个区域都可以看作为一个节点。
如图所示,该流网络可以看作为两个节点。割的净流为
。割的容量为
。
求最大径流量就是求其流网络的最小割。
五. Dinic算法
Dinic算法是先使用BFS将流网络进行分层,这样可以避免进行DFS寻找增广路径时出现重复的情况。
在进行DFS寻找增广路径时,下一节点必定在此节点的下一层。
DFS伪代码:
DFS(x, flow)
if x==汇点
return flow
for y in 邻接[x]
fxy = 边xy允许的流量最大值
r = DFS(y, min(flow, fxy))
if r≠ 0
更新边xy的权值
return r
return 0
在DFS完毕之后再次使用BFS对残留网络重新进行分层
Dinic算法伪代码:
while true
flag = BFS()
if !flag
break
while true
r = DFS(起点, infinity)
if r = 0
break
Dinic算法效率分析:
因为dinic的dfs按照层次来递归,因为每次扫描出的层数是递增的,而且不超过n,所以外循环bfs最多进行n次,而因为每次找增广路都有一条边作为“瓶颈”,一共有e条边,就有e个瓶颈,e条路径,要进行e次dfs,每次dfs复杂度为,总体复杂度为
</