Дейкстра на матрице смежности за O(V²) — когда это лучше, чем версия на куче?
Все показывают Дейкстру на priority_queue за O(E log V). Но я слышал, что есть версия без кучи за O(V²). В каких случаях квадратичная версия выгоднее? И как она выглядит?
2 ответа
Версия без кучи: на каждом из V шагов линейным проходом ищем ещё не закрытую вершину с минимальным dist, фиксируем её и релаксируем соседей. Никакой кучи.
vector<ll> dist(n, INF);
vector<bool> used(n, false);
dist[s] = 0;
for (int iter = 0; iter < n; iter++) {
int v = -1;
for (int i = 0; i < n; i++)
if (!used[i] && (v == -1 || dist[i] < dist[v])) v = i;
if (dist[v] == INF) break;
used[v] = true;
for (int u = 0; u < n; u++)
if (g[v][u] != INF && dist[v] + g[v][u] < dist[u])
dist[u] = dist[v] + g[v][u];
}
Сложность O(V²) по времени. Это выгоднее версии на куче O(E log V), когда граф плотный: при E ≈ V² куча даёт O(V² log V), а квадратичная версия — чистый O(V²). Грубое правило: плотный граф (E близко к V²) → O(V²) без кучи; разреженный (E ≈ V) → куча.
Ещё плюс квадратичной версии — отсутствие проблемы «протухших записей» в куче и меньшая константа, её проще написать без багов. Минус — память O(V²) под матрицу смежности (при V = 10^5 не влезет). На практике: V <= ~2000 и плотный граф — берите O(V²); большой разреженный — куча. Существует ещё Дейкстра на куче Фибоначчи за O(E + V log V), но в CP её не пишут — константа огромная.