← Все вопросы

Как посчитать количество кратчайших путей между двумя вершинами?

Задан 15 месяцев назад1.5к просмотров2 ответа
9

Нужна не длина кратчайшего пути из s в t, а сколько разных кратчайших путей существует (по модулю, число большое). Граф невзвешенный. Как это сделать вместе с BFS?

2 ответа

13
✓ Принятый ответ — помог автору

Ведём два массива: dist[v] (длина кратчайшего пути) и ways[v] (число кратчайших путей до v). При BFS, когда из v идём в соседа u:

  • если нашли u впервые (dist[u] ещё не установлено) → dist[u] = dist[v]+1, ways[u] = ways[v];
  • если пришли в u снова по кратчайшему (dist[v]+1 == dist[u]) → ways[u] += ways[v].
const int MOD = 1e9+7;
vector<int> dist(n, -1), ways(n, 0);
queue<int> q;
dist[s] = 0; ways[s] = 1; q.push(s);
while (!q.empty()) {
    int v = q.front(); q.pop();
    for (int u : g[v]) {
        if (dist[u] == -1) {
            dist[u] = dist[v] + 1;
            ways[u] = ways[v];
            q.push(u);
        } else if (dist[u] == dist[v] + 1) {
            ways[u] = (ways[u] + ways[v]) % MOD;
        }
    }
}
// ответ: ways[t]

Сложность O(V + E). ways обычно считают по модулю — число путей растёт экспоненциально.

6

Для взвешенного графа то же делается поверх Дейкстры, но аккуратнее: при строгом улучшении dist[u] мы перезаписываем ways[u] = ways[v] (старые пути перестали быть кратчайшими), а при равенстве dist[v]+w == dist[u] — прибавляем ways[u] += ways[v]. Главная грабля — не забыть сбрасывать счётчик при улучшении расстояния, иначе насчитаете лишнего от уже неактуальных путей.

Ваш ответ

Войдите, чтобы ответить на вопрос.