寻找最小瓶颈路径的线性时间算法
Linear-Time algorithm for finding a mininum-bottleneck path
我正在上斯坦福大学的在线算法class,其中一题如下:
Define the bottleneck of a path to be the maximum length of one of its
edges. A minimum-bottleneck path between two vertices s and t is a
path with bottleneck no larger than that of any other s-t path.
Suppose now that the graph is undirected. Give a linear-time (O(m))
algorithm to compute a minimum-bottleneck path between two given
vertices.
使用修改后的 Dijkstra 算法解决此问题,运行时间复杂度为 O(mlog(n)),不符合要求。 Wikipedia 声称
exists a linear time algorithm for finding a widest s-t path in an
undirected graph, that does not use the maximum spanning tree. The
main idea of the algorithm is to apply the linear-time path-finding
algorithm to the median edge weight in the graph, and then either to
delete all smaller edges or contract all larger edges according to
whether a path does or does not exist, and recurse in the resulting
smaller graph.
有几个问题。算法主要是手挥手,我不是在找最宽的路径,而是相反。
This 论文的文字比维基百科多,但它也没有深入细节,尤其是在收缩边缘时。
我写出了以下伪代码:
1: MBP(G, s, t)
2: if |E| == 1
3: return the only edge
4: else
5: x = median of all edge weights
6: E' = E - (v, w) where weight(v, w) < x
7: construct G'(V, E')
8: exists = is there a path from s to t in G'
9: if (exists == FALSE)
10: compute all the connected components Cᵢ of G'
11: reinsert the edges deleted into G'
12: G* = G'
13: for each Cᵢ
14: G* = SHRINK(G*, Cᵢ)
15: return MBP(G', s, t)
16: SHRINK(G, C)
17: leader = leader vertex of C
18: V* = {V(G) - C} ∪ {leader}
19: E* = {}
20: for each edge (v, w) ∈ E(G)
21: if v, w ∈ V*
22: E* = E* ∪ {(v, w, weight(v, w))}
23: else if v ∈ C, w ∈ V*
24: E* = E* ∪ {(leader, w, max(weight(v, w)))}
25: return G*(V*, E*)
有几点我不明白:
- 第 6 行:删除权重高于或低于中值的边有什么关系?
- 第20行:有3种边,两个顶点都在连通分量外,两个顶点都在连通分量内,一个顶点在连通分量内,一个在连通分量外。第一种类型保留其边缘权重,第二种类型变为自循环并应删除(?)。第三种边的权重应该是多少?
OP在这里。在my blog上找到了详细的解决方案,但伪代码如下:
1: CRITICAL-EDGE(G, s, t)
2: if |E(G)| == 1
3: return the only edge
4: else
5: x = median of all edge weights
6: X = E - (v, w) s.t. weight(v, w) > x
7: G' = G(V, X)
8: exists = is there a path from s to t in G'
9: if (exists == FALSE)
10: C = {C₁, C₂, ..., Cₖ} s.t. Cᵢ is a connected component of G
11: G' = G(V, E - X)
12: for i = 1 to |C|
13: G' = SHRINK(G', C, i)
14: else if X == E // no edges were deleted
15: X = {(v, w)} s.t. weight(v, w) = x
16: G' = G(V, X)
17: return CRITICAL-EDGE(G', s, t)
18: SHRINK(G, C, i)
19: leaderᵢ = leader vertex of C[i]
20: V* = {V(G) - C[i]} ∪ {leaderᵢ}
21: E* = {}
22: for each (v, w) ∈ E(G)
23: if v ∈ C[i], w ∈ C[j]
24: E* = E* ∪ {(leaderᵢ, leaderⱼ, min(weight(u, w)))} ∀ u ∈ C[i]
25: else if v, w ∉ C[i]
E * = E* ∪ {(v, w, weight(v, w))}
26: return G*(V*, E*)
我正在上斯坦福大学的在线算法class,其中一题如下:
Define the bottleneck of a path to be the maximum length of one of its edges. A minimum-bottleneck path between two vertices s and t is a path with bottleneck no larger than that of any other s-t path. Suppose now that the graph is undirected. Give a linear-time (O(m)) algorithm to compute a minimum-bottleneck path between two given vertices.
使用修改后的 Dijkstra 算法解决此问题,运行时间复杂度为 O(mlog(n)),不符合要求。 Wikipedia 声称
exists a linear time algorithm for finding a widest s-t path in an undirected graph, that does not use the maximum spanning tree. The main idea of the algorithm is to apply the linear-time path-finding algorithm to the median edge weight in the graph, and then either to delete all smaller edges or contract all larger edges according to whether a path does or does not exist, and recurse in the resulting smaller graph.
有几个问题。算法主要是手挥手,我不是在找最宽的路径,而是相反。
This 论文的文字比维基百科多,但它也没有深入细节,尤其是在收缩边缘时。
我写出了以下伪代码:
1: MBP(G, s, t)
2: if |E| == 1
3: return the only edge
4: else
5: x = median of all edge weights
6: E' = E - (v, w) where weight(v, w) < x
7: construct G'(V, E')
8: exists = is there a path from s to t in G'
9: if (exists == FALSE)
10: compute all the connected components Cᵢ of G'
11: reinsert the edges deleted into G'
12: G* = G'
13: for each Cᵢ
14: G* = SHRINK(G*, Cᵢ)
15: return MBP(G', s, t)
16: SHRINK(G, C)
17: leader = leader vertex of C
18: V* = {V(G) - C} ∪ {leader}
19: E* = {}
20: for each edge (v, w) ∈ E(G)
21: if v, w ∈ V*
22: E* = E* ∪ {(v, w, weight(v, w))}
23: else if v ∈ C, w ∈ V*
24: E* = E* ∪ {(leader, w, max(weight(v, w)))}
25: return G*(V*, E*)
有几点我不明白:
- 第 6 行:删除权重高于或低于中值的边有什么关系?
- 第20行:有3种边,两个顶点都在连通分量外,两个顶点都在连通分量内,一个顶点在连通分量内,一个在连通分量外。第一种类型保留其边缘权重,第二种类型变为自循环并应删除(?)。第三种边的权重应该是多少?
OP在这里。在my blog上找到了详细的解决方案,但伪代码如下:
1: CRITICAL-EDGE(G, s, t)
2: if |E(G)| == 1
3: return the only edge
4: else
5: x = median of all edge weights
6: X = E - (v, w) s.t. weight(v, w) > x
7: G' = G(V, X)
8: exists = is there a path from s to t in G'
9: if (exists == FALSE)
10: C = {C₁, C₂, ..., Cₖ} s.t. Cᵢ is a connected component of G
11: G' = G(V, E - X)
12: for i = 1 to |C|
13: G' = SHRINK(G', C, i)
14: else if X == E // no edges were deleted
15: X = {(v, w)} s.t. weight(v, w) = x
16: G' = G(V, X)
17: return CRITICAL-EDGE(G', s, t)
18: SHRINK(G, C, i)
19: leaderᵢ = leader vertex of C[i]
20: V* = {V(G) - C[i]} ∪ {leaderᵢ}
21: E* = {}
22: for each (v, w) ∈ E(G)
23: if v ∈ C[i], w ∈ C[j]
24: E* = E* ∪ {(leaderᵢ, leaderⱼ, min(weight(u, w)))} ∀ u ∈ C[i]
25: else if v, w ∉ C[i]
E * = E* ∪ {(v, w, weight(v, w))}
26: return G*(V*, E*)