Интерактивная лаборатория · 8–9 классы
Дейкстра: следим за каждой строкой
Выбери C++ или Python и наблюдай, как код извлекает минимум, улучшает расстояния и пропускает устаревшие записи.
Настрой эксперимент
Смена языка, графа или старта начинает выполнение заново. Цель нужна для показа итогового пути; алгоритм ищет расстояния до всех вершин.
Граф и расстояния
Под вершиной — dist. Оранжевое ребро сейчас проверяется; зелёный маршрут появится после завершения. «Подтверждено» — пояснение на рисунке, отдельного массива visited в коде нет.
Рёбра и список смежности
Соседи упорядочены по номеру для повторяемости примера. Самому алгоритму такая сортировка не нужна.
Очередь с приоритетом q
Каждая карточка — пара (расстояние, вершина). Первая обведена оранжевым.
Показан порядок извлечения, а не внутренний массив кучи. Серые записи устарели: они останутся в очереди до извлечения и проверки.
Предскажи следующий минимум
Какую запись извлекли бы сейчас? Старая запись тоже может оказаться первой.
Таблица путей
| v | dist[v] | parent[v] | Расстояние |
|---|
Во время работы ∞ означает «ещё не найдено», после завершения — «недостижимо». parent = −1 показан прочерком.
Код C++17
Подсветка показывает только что выполненную строку. Таблица и переменные — состояние после этого шага. Закрывающие скобки C++ обозначают выход из области видимости.
- dist[s] = 0;
- q.push({0, s});
- while (!q.empty()) {
- auto [du, v] = q.top();
- q.pop();
- if (du != dist[v]) {
- continue;
- }
- for (auto [u, w] : adj[v]) {
- long long nd = du + w;
- if (nd < dist[u]) {
- dist[u] = nd;
- parent[u] = v;
- q.push({nd, u});
- }
- }
- }
- dist[s] = 0
- heappush(q, (0, s))
- while q:
- du, v = heappop(q)
- if du != dist[v]:
- continue
- for u, w in adj[v]:
- nd = du + w
- if nd < dist[u]:
- dist[u] = nd
- parent[u] = v
- heappush(q, (nd, u))
Готовы к старту
Нажми «Следующая строка».
Переменные
- s
- —
- du
- —
- v
- —
- u
- —
- w
- —
- nd
- —
s — старт; v — извлечённая вершина; du — расстояние в записи; u — сосед; w — вес; nd — новая стоимость. Прочерк означает «ещё не задана» или «вне области видимости».
Подготовка данных перед кодом
#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#include <utility>
#include <algorithm>
using namespace std;
// n — число вершин, s — старт (номера от 1 до n).
// adj[v] содержит пары {сосед, вес}.
const long long INF = 1LL << 62;
vector<long long> dist(n + 1, INF);
vector<int> parent(n + 1, -1);
using State = pair<long long, int>;
priority_queue<State, vector<State>, greater<State>> q;from heapq import heappush, heappop
# n — число вершин, s — старт (номера от 1 до n).
# adj[v] содержит пары (сосед, вес).
INF = float("inf")
dist = [INF] * (n + 1)
parent = [-1] * (n + 1)
q = []adj уже заполнен рёбрами выбранного графа. Все веса ≥ 0. Здесь приведено ядро алгоритма; полный ввод и вывод есть на учебной странице.
Что важно заметить?
- Выбираем минимум расстояния, а не номера вершины.
- Найденное расстояние может улучшаться до подтверждения.
- Обновление dist, parent и очереди — три разные строки.
- Старая запись не меняет уже найденный короткий путь.
- При равной стоимости не добавляем новую запись: используем <.