← Олимпиадное программирование
Интерактивная лаборатория · 8–9 классы

Дейкстра: следим за каждой строкой

Выбери C++ или Python и наблюдай, как код извлекает минимум, улучшает расстояния и пропускает устаревшие записи.

Настрой эксперимент

Смена языка, графа или старта начинает выполнение заново. Цель нужна для показа итогового пути; алгоритм ищет расстояния до всех вершин.

0 / 0

Граф и расстояния

Граф ДейкстрыСписок рёбер доступен в спойлере ниже.
Не найденоОценкаПодтвержденоТекущая вершина

Под вершиной — dist. Оранжевое ребро сейчас проверяется; зелёный маршрут появится после завершения. «Подтверждено» — пояснение на рисунке, отдельного массива visited в коде нет.

Рёбра и список смежности

Соседи упорядочены по номеру для повторяемости примера. Самому алгоритму такая сортировка не нужна.

Очередь с приоритетом q

Каждая карточка — пара (расстояние, вершина). Первая обведена оранжевым.

Показан порядок извлечения, а не внутренний массив кучи. Серые записи устарели: они останутся в очереди до извлечения и проверки.

Предскажи следующий минимум

Какую запись извлекли бы сейчас? Старая запись тоже может оказаться первой.

Таблица путей

vdist[v]parent[v]Расстояние

Во время работы ∞ означает «ещё не найдено», после завершения — «недостижимо». parent = −1 показан прочерком.

Код C++17

Подсветка показывает только что выполненную строку. Таблица и переменные — состояние после этого шага. Закрывающие скобки C++ обозначают выход из области видимости.

  1. dist[s] = 0;
  2. q.push({0, s});
  3. while (!q.empty()) {
  4. auto [du, v] = q.top();
  5. q.pop();
  6. if (du != dist[v]) {
  7. continue;
  8. }
  9. for (auto [u, w] : adj[v]) {
  10. long long nd = du + w;
  11. if (nd < dist[u]) {
  12. dist[u] = nd;
  13. parent[u] = v;
  14. q.push({nd, u});
  15. }
  16. }
  17. }

Готовы к старту

Нажми «Следующая строка».

Переменные

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;

adj уже заполнен рёбрами выбранного графа. Все веса ≥ 0. Здесь приведено ядро алгоритма; полный ввод и вывод есть на учебной странице.

Что важно заметить?
  • Выбираем минимум расстояния, а не номера вершины.
  • Найденное расстояние может улучшаться до подтверждения.
  • Обновление dist, parent и очереди — три разные строки.
  • Старая запись не меняет уже найденный короткий путь.
  • При равной стоимости не добавляем новую запись: используем <.
Вернуться к объяснению →