Возникли проблемы с вычислением APSP для размера матрицы n >= 4

У меня возникли проблемы с поиском проблемы со следующей реализацией алгоритма APSP Флойда-Уоршалла.

В настоящее время я работаю над упражнением vjudge, и мне не удается понять, в чем проблема с выполнением этого упражнения.

Краткое описание проблемы:

Учитывая ориентированный граф с n узлами (где n не более 500), матрицу смежности всех расстояний между ними и список n узлов, определяющий порядок удаления узлов из этого графа, выполните следующий процесс:

Перебирайте список узлов, которые нужно удалить. На каждом этапе к ответу (который начинается с 0) добавляется сумма кратчайших расстояний между каждой упорядоченной парой различных неудаленных узлов графа. Затем удалите текущий узел в списке из графа, что может изменить кратчайшие расстояния для последующих итераций. В конце выведите ответ.

Полная постановка задачи:

После многих лет планирования Галактическая Империя построила планетарную крепость Джеонозис, идеальную тюрьма для лидеров восстания и особое место, отведенное для злого Люка Скайуокера. Однако, как показали неудачи Звезды Смерти I и II, крепость не идеальна и злой Альянс повстанцев планирует использовать слабость, обнаруженную в окружающих башнях связи. Джеонозис.

Чтобы реализовать свои коварные планы, Альянс повстанцев украл карту со структурой крепости. На Джеонозисе есть коммуникационный комплекс, состоящий из n башен. Каждая пара башен комплекса соединены линиями электропередачи, которые отправляют сообщения по затратам энергии. Повстанцы хотят построить корабль «Изгой-два», чтобы разрушить крепость и спасти ее пленников. К Чтобы добиться этого, им придется разрушить все башни крепости. Они обнаружили, что сила необходимое для разрушения башни равно сумме минимальной энергии, необходимой для отправки сообщения между каждой парой крепостных башен либо прямо, либо опосредованно через другие башни.
Обратите внимание: как только башня разрушена, она перестает учитываться в этой формуле.

С другой стороны, командир Разбойника-Два очень капризен и хочет уничтожить башни в заданном порядке. Зная информацию о башнях связи на Джеонозисе и порядок, в котором каждая башня будет разрушена, можете ли вы сказать, какая мощность необходима для Разбойника-Два? выполнить свою миссию?

Для матриц n < 4 у меня нет проблем, но моя проблема возникает с матрицами, такими что n >= 4.

Я считаю, что первый цикл, с одной стороны, не нужен, поскольку у меня уже есть матрица стоимости графа. Во-вторых, это может быть причиной моего неправильного результата.

Вот ссылка на упражнение: Геонозис (UVA-13211)

#include <iostream>
#include <vector>
#include <limits>

using namespace std;
const int INFTY = numeric_limits<int>::max(); // Use numeric_limits for infinity

// Graph representing the Geonosis Map.
struct Graph {
    vector<vector<int>> costo;

    explicit Graph(int n) {
        costo.resize(n, vector<int>(n));
    }
};

// Floyd-Warshall implementation APSP.
void APSP(const Graph& geonosis, vector<vector<int>>& dist) { // Pass dist by reference (improves space complexity=
    unsigned long n = geonosis.costo.size();

    // Initialize dist with the given graph's costo
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (i == j) {
                dist[i][j] = 0;
            } else if (geonosis.costo[i][j] != 0) {
                dist[i][j] = geonosis.costo[i][j];
            }
        }
    }

    // Compute all pair shortest paths using Floyd-Warshall algorithm
    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (geonosis.costo[i][k] != INFTY && geonosis.costo[k][j] != INFTY) {
                    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }
    }
}

int solve(int t) {
    while (t--) {
        int n;
        unsigned long long res = 0;
        cin >> n;
        cin.ignore();  // to ignore the newline after the number.

        // to create my case matrix and return the shortest path to destroy all towers.
        Graph geonosis(n);
        vector<int> destOrder(n);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                cin >> geonosis.costo[i][j];
            }
        }

        // we make a sequence that stores the dest. order for the case.
        for (int i = 0; i < n; ++i) {
            cin >> destOrder[i];
        }

        vector<vector<int>> dist(n, vector<int>(n, INFTY));

        APSP(geonosis, dist);
        // once we finish executing APSP, dist matrix has the shortest path from each vertex i to each vertex j while i != j.
        // we want to keep track of the towers that have been destroyed
        vector<bool> destroyed(n, false);

        for (int d = 0; d < n; ++d) {
            int currentTower = destOrder[d];

            unsigned long long currentSum = 0;
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (!destroyed[i] && !destroyed[j] && dist[i][j] != INFTY) {
                        currentSum += dist[i][j];
                    }
                }
            }

            destroyed[currentTower] = true;
            // Add the current sum to the total sum
            res += currentSum;
        }

        // Print the total sum of all shortest paths
        cout << res << endl;
    }
    return 0;
}

int main() {
    int t;
    cin >> t;
    solve(t);
    return 0;
}

Я попытался реализовать это упражнение с использованием алгоритма Данцига для расчета APSP, но оно по-прежнему возвращает тот же результат. Я даже не могу точно определить проблему во время отладки.

Пробовали ли вы отлаживать свою программу? Например, используя отладчик для пошагового выполнения кода, отслеживая переменные и их значения, чтобы увидеть, что происходит на самом деле?

Some programmer dude 20.07.2024 20:58

После многих лет планирования Галактическая Империя построила планетарную крепость Джеонозис. Я знаю, что вы новичок, но вам следует точно писать о том, какая у вас проблема, а не рассказывать истории. Причина, по которой рассказывать истории вместо того, чтобы переходить к вопросу, неразумно, заключается в том, что многие из тех, кто мог бы вам помочь, просто не захотят тратить свое время на чтение подобных вещей. Если проблема в реализации алгоритма Флойда-Уоршалла, это все, что вам нужно упомянуть.

PaulMcKenzie 20.07.2024 22:06

@PaulMcKenzie Я добавил формулировку проблемы к вопросу, чтобы избежать гниения ссылок. Я отредактировал более краткое техническое описание проблемы. (Проблема не в реализации соглашения Флойда-Уоршалла.)

Unmitigated 21.07.2024 00:56
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема с вашим кодом заключается в том, что вы запускаете Floyd-Warshall только один раз и не обрабатываете удаление узлов должным образом. Когда узел уничтожается, вы игнорируете только пути, которые начинаются или заканчиваются в узле, не учитывая тот факт, что кратчайший путь между другими парами узлов, возможно, уже использовал ребро, проходящее через разрушенный узел. Фактически, единственный способ справиться с удалением узла — это перестроить всю матрицу кратчайших путей, что каждый раз слишком медленно.

Вместо этого обратите внимание, что порядок выполнения операций, подразумеваемый формулировкой задачи, ведет вас к неэффективному решению. Если вы проходите по уничтоженным узлам в обратном порядке, то каждый раз вы добавляете в граф новый узел, а не уничтожаете узел, поэтому обновление кратчайших путей можно выполнить за O(N^2).

Вот рабочее решение:

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
    int t, n;
    for (std::cin >> t; t--;) {
        std::cin >> n;
        std::vector<std::vector<int>> cost(n, std::vector<int>(n));
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j)
                std::cin >> cost[i][j];
        std::vector<int> order(n);
        for (int& o : order) std::cin >> o;
        long long totalPower = 0;
        std::vector<bool> active(n);
        for (int i = n - 1; i >= 0; --i) {
            active[order[i]] = true;
            for (int j = 0; j < n; ++j)
                for (int k = 0; k < n; ++k) {
                    cost[j][k] = std::min(cost[j][k], cost[j][order[i]] + cost[order[i]][k]);
                    if (active[j] && active[k]) totalPower += cost[j][k];
                }
        }
        std::cout << totalPower << '\n';
    }
}

Вы даже не представляете, как сильно вы мне помогли. Я новичок в вопросах переполнения стека, поэтому извините за длину вопроса, но я искренне ценю ваше потраченное время.

str8 21.07.2024 21:07

@str8 Рад помочь. :)

Unmitigated 21.07.2024 21:08

Другие вопросы по теме