• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Modyfikacja algorytmu Dijkstry

0 głosów
815 wizyt
pytanie zadane 16 stycznia 2023 w C i C++ przez polandonion Dyskutant (7,710 p.)
edycja 16 stycznia 2023 przez polandonion

Siemka ponownie, tym razem mam kłopot z zadaniem Przemytnicy z X OI, I etap. Od razu zauważyłem, że w tym zadaniu trzeba wykorzystać algorytm Dijkstry. Oto moje spostrzeżenia nt. tego zadania:

Zauważyłem, że można oprócz tablicy dis[x], (która przechowuje min. odległość od wierzchołka 1. do x) zrobić tablicę disTo1[x], która przechowywać będzie min. odległość z wierzchołka x do 1 (o ile istnieje).

Tutaj załączam tabelkę, która zwizualizuje wam ten problem i zadanie stanie się proste do zrozumienia: link. Suma sum jest równa sumie dis[x], disTo1[x] oraz połowy val[x], gdyż cło wynosi połowę przewożonego ładunku.

Jedyny problem dla mnie to jakiś wydajny sposób na stworzenie tablicy disTo1[x]. Ma ktoś pomysł i zechciałby się nim podzielić? I jak to zrobić tak, aby nie lecieć n (gdzie n to liczba wierzchołków) razy algorytmem Dijkstry?

Jak do tej pory napisałem tyle:

[on-line]

#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;

vector <pair <int, int>> v[5001];
priority_queue <pair <int, int>> q;
int dis[5001], disTo1[5001], val[5001], sum[5001];
bool vis[5001];
const int INF = 1e9 + 1;
int n;

void dij(int w) {
    for (int i = 2; i <= n; i ++)
        dis[i] = INF;
    dis[1] = 0;

    q.push({0, w});
    while (!q.empty()) {
        w = q.top().y;
        q.pop();

        if (vis[w])
            continue;
        vis[w] = 1;

        for (auto a : v[w]) {
            dis[a.x] = min(dis[a.x], dis[w] + a.y);
            if (!vis[a.x])
                q.push({-dis[a.x], a.x});
        }
    }
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i ++)
        cin >> val[i];

    int k;
    cin >> k;
    while (k --) {
        int a, b, c;
        cin >> a >> b >> c;
        v[a].push_back({b, c});
    }

    dij(1);

    /* for (int i = 1; i <= n; i ++)
        cout << i << ' ' << dis[i] << '\n'; */
}

1 odpowiedź

+1 głos
odpowiedź 16 stycznia 2023 przez Whistleroosh Maniak (57,400 p.)
wybrane 17 stycznia 2023 przez polandonion
 
Najlepsza
Tu trzeba zastosować jeden prosty trick. Dijsktra liczy najkrótsze ścieżki ze źródła, a Ty musisz policzyć najkrótsze ścieżki do źródła. Trick sprowadza się do pewnej modyfikacji grafu i uruchomieniu Dijkstry jeszcze raz, jakiej modyfikacji?
komentarz 16 stycznia 2023 przez polandonion Dyskutant (7,710 p.)
nie mam pojęcia, chociaż jedyne co mi świta to zamiana grafu na taki z przeciwnymi krawędziami, choć to by raczej nie miało sensu.
komentarz 16 stycznia 2023 przez Whistleroosh Maniak (57,400 p.)
Właśnie wbrew pozorom ma to sens i to jest poprawne rozwiązanie
komentarz 16 stycznia 2023 przez polandonion Dyskutant (7,710 p.)
aha, już rozumiem, dzięki wielkie. Ruszam do implementacji
komentarz 16 stycznia 2023 przez polandonion Dyskutant (7,710 p.)
100% za zadanie, dzięki za podpowiedź

Podobne pytania

0 głosów
1 odpowiedź 1,137 wizyt
0 głosów
1 odpowiedź 457 wizyt
pytanie zadane 7 stycznia 2021 w C i C++ przez wodzu_37 Nowicjusz (160 p.)

93,731 zapytań

142,669 odpowiedzi

323,286 komentarzy

63,291 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...