dijkstra alg U = {v} # U是已经寻找到最短路径的节点 S = V - {v} # 待寻找的节点 D 一个从源点到其他节点的最短距离 while S 不为空: 从S中选择一个距离最小的节点 u U = U ∪ {u} S = S - {u} for u所有邻边 (u, w): if w∈S and D[u]+length(u, w) < D[w]: D[w] = D[u] + length(u, w) return D
Let’s say you have G = (V, E) a bipartite graph, separated between X and Y.
As you said, first you have to find a maximum matching (which can be achieved with Dinic’s algorithmfor instance). Let’s call M this maximum matching.
Then to construct your minimum vertex cover顶点覆盖:
Find U the set (possibly empty) of unmatched vertices in X, ie. not connected to any edge in M
Build Z the set or vertices either in U, or connected to U by alternating paths (paths that alternate between edges of M and edges not in M) 通过交替路径与U中顶点相连。
Then K = (X \ Z) U (Y ∩ Z) is your minimum vertex cover
BiMatch2 Input: 二分图 G = (X ∪ Y, E) Output: G中最大匹配M 初始化M为任意匹配(可能为空) while存在自由顶点x和自由y顶点 设r为一个自由x顶点,采用广度优先搜索,生成一棵以r为根的交替路径树T if T为匈牙利树: let G <- G - T else: 在T中找到一条增广路径p,并设M = M + p
GMATCH Input: undirected graph G(V, E) Output: maximum match M of G
M = {} maximum = false while not maximum 确定与M相关的自由顶点集F augment = false while F ≠ {} and not augment 清空栈、未标记边,从顶点删除标记 设x为下一个顶点; F = F - {x}; T = x 标记x为外部的 {初始化交替路径树} hungarian = false while not augment: 选择一个外部顶点x和一条未标记的边(x, y) if (x, y)存在: 标记(x, y) else: hungarian = true break if y是内部的: doNothing {找到偶数长的回路} elif y是外部的: {找到花} 将花放到栈顶,收缩花 用顶点w替换花,标记w是外部的 如果花包含根,则标记w是自由的 elif y是自由的: augment = true F = F - {y} else: 设(y, z)在M中,将(x, y) 和(y, z)加入T中 标记y是内部的,z为外部的 if hungarian: 从G中移除T elif augment: 构造增广路径:从栈中弹出花,展开它们,增加偶数长部分 用p增广G if not augment: maximum = true
福特福克森方法每次选择一条增广路径,并用该增广路径的瓶颈容量来扩大网络流。add some introduction to residence graph(R)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Alg 161 Ford-Fulkerson Input 网络(G, s, t, c) Output: G 中的一个流 初始化剩余图 R = G for (u, v) 属于 E f(u, v) = 0 end for while 在R中有一条增广路径 p = s,.., t: 设Δ为p的瓶颈容量 for p 中的每条边(u, v): f(u, v) = f(u, v) + Δ end for 更新剩余图R end while
1 Alg 最小路径长度增值 MPLA 2 Input (G, s, t, c) 3 Output G的最大流 4 for (u, v) in E: 5 f(u, v) = 0 6 end for 7 初始化剩余图,R=G 8 查找R的层次图L 9 while t in L: 10 while 在L中t可以从s到达: 11 let p=L中s->t的一条路径 12 设Δ为p的瓶颈容量 13 用Δ增值当前流 14 沿着路径p更新L和R 15 end while 16 用剩余图R计算新的层次图L 17 end while
Alg Dinic 阻塞流算法 Input (G, s, t, c) Output G的最大流 for (u, v) ∈ E: f(u, v) = 0 初始化剩余图 R = G 搜索层次图 L while t 为 L中的顶点: u = s p = u while outdegree(s) > 0 and u != t: while u != t and outdegree(s) > 0:# 前进搜索出一条增广路径 if outdegree(u) > 0: suppose (u,v)为L中一条边 p = p, v u = v else: 删除L中 u 的邻接边 删除p最末尾顶点u,且令p的倒数第二个节点为u if u == t: 假设p的瓶颈容量为Δ,沿着p推送一个Δ的流。 修改层次图和剩余图 把u置为修改层次图后s在路径p上能达到的最后一个顶点,注意u可能是s 计算新的层次图(根据剩余图)
最外层的循环对应于n-2个层次图(阶段),每个阶段内通过深度优先的方式来寻找增广路径。每寻找到一条增广路径 (语句if u == t)就用路径p的瓶颈容量进行增值。
它的时间复杂性分析如下,n-2个外层循环,每个外层循环内要深度优先遍历整张图并附带删除顶点和边 (m + n)。对于每一条增广路径增值的时间为 n (即沿着路径p推流,修改层次图和剩余图),最多有m跳增广路径,时间为(nm)。故总的时间复杂性为$O(n^2m)$
阻塞流(Dinic) 算法能够在$O(n^2m)$内找到有向图的最大流
MPM算法
MPM算法相比于Dinic算法寻找到了一个更快的寻找阻塞流的算法$O(n^2)$
顶点v的通过量(throughput),为引入边的总容量和引出边的总容量两者中的小值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Algorithm MPM Input (G, s, t, c) Output G的最大流 for (u, v) ∈ E: f(u, v) = 0 初始化剩余图 R = G 查找剩余图R的层次图L while t 为 L中的层次图顶点: while t 在L中从s能到达: 查找最小通过量的顶点v(设其对应值为g) 从v到t推下g个单元流 从s到v拉入g个单元流 更新 f, L, R 使用剩余图R计算新的层次图L
alg 14.5 RandomSampling inputs m, n (m<n) outputs {1...n}中选择的m个元素 for i =1:n S[i] = False # S 为一个表示元素是否被选择的bool数组 k = 0 while k < m: r = random(1, n) if not S[r]: k += 1 A[k] = r S[r] = True return A