Alterna · учебный материал

Shorter Paths and MST

Dakestra, A* with hisristics, Bellman-Ford, MST (Prime/Crascal), Visualizers and algorithm comparison.

Что в этом материале

Содержание и основные понятия

Back to the table of contents
Alterna chapter 24 page 24.2
Shorter Paths and MST
Dakestra, A*, Bellman-Ford.
The navigators, router protocols (OSPF, BGP), and games (PathFinding) all use the shortest route algorithms.
GEF
PIF
EGE No. 1
Olympic
01
Dakestra algorithm
The Dakestra algorithm is finding a quick way from one launch top to everyone else in the
weighted graph with non-negative weights
.
Ideas
Greedy algorithm: Support the current known distance to each top.
Minimum
It's not gonna get any shorter.
Initiation: dist[start] = 0, dist [v] = \ for all v \start.
New
priority line
(min-heap), add all vertices with dist[v].
Remove the top
u
with the minimum dist is the current "near" unattended summit.
Relaxation
: for each rib u of w: if dist[u] + w <dist[v] update dist [v] = dist][u]+w.
Repeat steps 3-4 until the line is empty.
After completion, the dist contains the shortest distance from star to all achievable vertebrates.
Example: 6 vertices
Count: A.B(7), A.C.(3), B.D(2), C.B.(1), C?E.(5), D.F.(6), E.F.2., B, E(8).
Step
u
dist[A]
dist[B]
dist[C]
dist[D]
dist[E]
dist[F]
0
—
0
∞
∞
∞
∞
∞
1
A
0
7
3
∞
∞
∞
2
C
0
4
3
∞
8
∞
3
B
0
4
3
6
8
∞
4
D
0
4
3
6
8
12
5
E
0
4
3
6
8
10
The shortest path is A.C.B.E.F.
Complexity
C
Binary piles
: O(V + E) log V. Each vertice is removed once from a pile (V · log V), each rib is treated when relaxed (E · Log V).
C
♪ A bunch of
(Theoretically): O(V · log V + E) is the optimal but difficult to implement.
Limitation
Algoritm
does not work with negative weights
Cause: Greedy setting of distance: If a negative weight rib appears later, the "recorded" distance will not be correct and cannot be corrected.
import heapq
def dijkstra(graph, start):
# graph[v] = [(u, w), ...] — список рёбер v→u с весом w
dist = {v: float('inf') for v in graph}
dist[start] = 0
pq = [(0, start)] # (расстояние, вершина)
while pq:
d, v = heapq.heappop(pq)
if d > dist[v]: continue # устаревший элемент
for u, w in graph[v]:
nd = d + w
if nd < dist[u]:
dist[u] = nd
heapq.heappush(pq, (nd, u))
return dist
# Пример:
graph = {
'A': [('B', 7), ('C', 3)],
'B': [('D', 2), ('E', 8)],
'C': [('B', 1), ('E', 5)],
'D': [('F', 6)],
'E': [('F', 2)],
'F': []
}
dist = dijkstra(graph, 'A')
print(f"A→F = {dist['F']}") # 10
print(f"Путь: A → C → B → E → F")
🐍
Dakestra: Animation of the code
02
A* - Dakestra + Heuristics
A* minimizes
f(v) = g(v) + h(v)
where:
g(v)
- The real cost of the start-up to v road (like Dakestra's).
h(v)
- Heuristics: valuation from v to target.
When h 0, A* becomes a normal Dakestra, the Euristics directs the search to the target, reducing the number of vertebrates treated.
Grid Euristics
Euristics
Formula
Movement
Manhattan
|x₁ − x₂| + |y₁ − y₂|
4-point grid
Euclidova
√((x₁ − x₂)² + (y₁ − y₂)²)
Any direction
Fuck you!
max(|x₁ − x₂|, |y₁ − y₂|)
8-point grid
Heuristic tolerance
Euristics
allowed
(admissible) if h(v) ≤ h*(v), for all v, where h* (v) is the true value before the target.
monotonne
(golderov: h(a) ≤ cost(a,b) + h(b)), A* guarantees the optimal path.
Comparison with Dakestra
A* is faster than Dakestra in practice if heuristics is good. In the worst case (h × 0 or bad heuretics) is the same complexity as Dakestrea: O((V+E)·log V).
import heapq
def astar(graph, start, goal, h):
# h(v) — эвристика: оценка расстояния от v до goal
open_set = [(h(start), 0, start)] # (f, g, v)
g_score = {start: 0}
came_from = {}
while open_set:
f, g, v = heapq.heappop(open_set)
if v == goal:
# восстановление пути
path = []
while v in came_from:
path.append(v)
v = came_from[v]
path.append(start)
return path[::-1], g_score[goal]
if g > g_score.get(v, float('inf')):
continue
for u, w in graph.get(v, []):
ng = g + w
if ng < g_score.get(u, float('inf')):
came_from[u] = v
g_score[u] = ng
nf = ng + h(u)
heapq.heappush(open_set, (nf, ng, u))
return None, float('inf') # путь не найден
# Пример сетки 4×4, Манхэттенская эвристика:
def manhattan(a, b, cols=4):
return abs(a // cols - b // cols) + abs(a % cols - b % cols)
grid = {(i, j): [] for i in range(4) for j in range(4)}
# ... строим граф из соседних клеток ...
# path, cost = astar(grid, start=0, goal=15, h=lambda v: manhattan(v, 15))
🧭
A* on the grid: interactive visualizer
Start
Objective
Open
Closed
Obstruction
03
Bellman-Ford (negative weights)
Unlike Dakestra, Bellman-Ford's algorithm works with
negative weights
and
Detecting Negative Cycles
The price is more complex.
Algoritm
Initiation: dist[start] = 0, dist [v] = \ for all v \start.
Repeat
V - 1 time
: For each rib (u, v, w) to relax: if dist[u] + w <dist[v], update dist [v] =dist [u]+w.
Negative cycle test
: To walk all the ribs again. If one distance is reduced, the graph has a negative cycle that can be achieved from the start.
Why is V - 1 iteration?
The shortest path without cycles contains
maximum V - 1 rib
For each iteration, the algorithm "detects" the shortest distance to k ribs (k is the iteration number).
Complexity
O(V · E)
- on each of the V - 1 iterations, we go around all the E ribs, slower than Dakestra, but at the same time maintain negative weights.
Negative cycle
Count: A.B. (1), B.C.(-3), C.B(1). The path B.O.C.1B: total weight -3 + 1 = -2. Negative weight cycle - distance can be reduced indefinitely. The algorithm will detect this on the Vth iteration.
When to use
Bellman-Ford is needed when there are negative-weight ribs in the box (e.g. financial models with "incomes") or when there is a need to check the existence of negative cycles. The other cases are preferred by Dakestra.
04
MST: Prem and Krascal
MST (Minimum Spanning Tree)
- Sub-graph connecting all vertices with
Minimum weight
and without cycles. MST is exactly V - 1 rib.
Kruscal Theorem
All MSTs in one row have the same total value. If all weights are different, MST is unique.
Prima algorithm
Start at any top.
Of all the ribs connecting visited and unattended vertices, choose
minimum
.
Add a rib and a new top.
Repeat until all V vertices are visited.
Complexity:
O((V+E)·log V) with a pile (with a dense graph - O(V2)).
Better for
dense
Countess.
Krascal algorithm
To sort all ribs by weight.
Take ribs in order (from smaller to larger).
Add if rib
does not form a cycle
(DSU check is a structure of "non-transgressive multiples").
Repeat until V-1 rib is added.
Complexity:
O(m · log m) where m =
Better for
Diluted
Countess.
🌲
Prim: step-by-step construction of MST
05
Comparison of algorithms
Algoritm
Complexity
Weights of Orts
Appointment
Specialities
Dakestra
O((V+E)·log V)
None
The Shortest Way From One Top
Greedy, non-negative weights
A*
O((V+E)·log V)*
None
PathFinding with Heuristics
Faster than Dakestra at good h(v)
Bellman-Ford
O(V·E)
Yes
Negative weights, cycles
Detecting cycles.
Floyd-Worsell.
O(V³)
Yes
All pairs of tops
Matrix implementation
Minimum Axis (MTS)
Accept.
O((V+E)·log V)
—
MST
Better for dense graphs.
Painted
O(m·log m)
—
MST
Better for the diluted graphs
* The complexity of A* depends on the quality of heuristics. In the worst case, it is O((V+E)·log V) like Dakestra.
The

Structural map of textbooks