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

Jaką ten algorytm ma złożonność?, Zadanie Zawody 1 etap OI, Algorytm Dijkstry

Object Storage Arubacloud
0 głosów
176 wizyt
pytanie zadane 12 lutego 2023 w Algorytmy przez pasjonat_algorytmiki Pasjonat (19,540 p.)
edycja 12 lutego 2023 przez pasjonat_algorytmiki

Natknąłem się na zadanie Zawody z 1 etapu XI OI: https://szkopul.edu.pl/problemset/problem/UiDG8sd_wsS2RfUPL3zQQ1XW/site/?key=statement

Napisałem algorytm, który wydaje mi się, że działa w O(N^2 * lg(N) ), odpalam Dijkstrę z każdego wierzchołka x, do którego wychodzi krawędź z wierzchołka 1 -> x (wierzchołek 1 to wejściowy). Kod wchodził na 70pkt, ale po dodaniu linii 57 i 58(żeby nie iśc niepotrzebnie tą Dijkstrą, jak wynik i tak będzie większy) daje 100pkt z bardzo dużym zapasem. Myślałem, że to poprostu przyśpieszy, ale myślałem, że nie wejdzie na 100, bo dalej jest O(N^2 * lg(N)). Więc zastanawiam się, czy złożonność się amortyzuje do lepszej złożonności, czy poprostu dlatego, że jest tylko 10 testów właściwych + 5 przykładowych(W wszystkich się szybko kończy)? W ksiażce "Przygody Bajtazara 25 lat Olimpiady Informatycznej" jest opisane rozwiązanie O((N+M) * lg(N)), którego jeszcze nie rozumiem, ale tez używają tam Dijkstry. Poglądowy rysunek mojego rozwiązania, jakbym źle opisał. Na czerwono zaznaczone wierzchołki, z których puszczam Dijkstrę(osobno), na zielono jakieś przykładowe wierzchołki z krawędziami(gdzie zwroty to wierzchołki), a wierzchołek "wejsciowy", ma numer 1.

Kod:

#include <iostream>
#include <vector>
#include <set>

using namespace std;

struct Krawedz
{
    int do_kogo;
    int waga;
};

struct Element_seta
{
    int wierzcholek;
    int wartosc;
    bool operator < (const Element_seta &element_seta) const
    {
        if (wartosc == element_seta.wartosc)
            return wierzcholek < element_seta.wierzcholek;
        return wartosc < element_seta.wartosc;
    }
};

int n = 0, m = 0, a = 0, b = 0, c = 0, d = 0, wyn = 0, min_wyn = 1e9+20;
vector<vector<Krawedz>> krawedzie;
vector<int> dp;
set<Element_seta> S;

int main()
{
    // O(N^2 * lg(N))???
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> m;
    krawedzie.assign(n+1,{});
    dp.assign(n+1,-1);
    for (int i = 0; i < m; ++i)
    {
        cin >> a >> b >> c >> d;
        krawedzie[a].push_back({b,c});
        krawedzie[b].push_back({a,d});
    }

    for (int i = 0; i < krawedzie[1].size(); ++i)
    {
        fill(dp.begin(),dp.end(),-1);
        S.clear();
        dp[krawedzie[1][i].do_kogo] = krawedzie[1][i].waga;
        S.insert({krawedzie[1][i].do_kogo,krawedzie[1][i].waga});
        wyn = -1;
        while(!S.empty())
        {
            Element_seta spr = *S.begin();
            if (spr.wartosc > min_wyn)
                break;
            S.erase(spr);
            if (spr.wierzcholek == 1)
            {
                wyn = spr.wartosc;
                break;
            }
            for (int j = 0; j < krawedzie[spr.wierzcholek].size(); ++j)
            {
                int v = krawedzie[spr.wierzcholek][j].do_kogo;
                if (v == 1 && spr.wierzcholek == krawedzie[1][i].do_kogo)
                    continue;
                if (dp[v] == -1 || spr.wartosc + krawedzie[spr.wierzcholek][j].waga < dp[v])
                {
                    auto it = S.find({v,dp[v]});
                    if (it != S.end())
                        S.erase(*it);
                    dp[v] = spr.wartosc + krawedzie[spr.wierzcholek][j].waga;
                    S.insert({v,spr.wartosc + krawedzie[spr.wierzcholek][j].waga});
                }
            }
        }
        if (wyn != -1)
            min_wyn = min(min_wyn,wyn);
    }

    cout << min_wyn << '\n';

    return 0;
}

Z góry dziękuję za pomoc i poświęcony czas!

1 odpowiedź

+1 głos
odpowiedź 13 lutego 2023 przez Whistleroosh Maniak (56,980 p.)
wybrane 13 lutego 2023 przez pasjonat_algorytmiki
 
Najlepsza

Chyba takie coś by się skwadraciło. Dijsktre startujemy z kolejnych wierzchołków od lewej do prawej. Ogólnie dla n <= 5000 złożoność O(n^2logn) nie jest aż taka zła. Powinna wystarczyć żeby zdobyć większość punktów. O ile ktoś specjanie nie da testów z pesymistycznym przypadkiem to dla losowego grafu Twój algorytm powinien chyba całkiem szybko działać. 

komentarz 13 lutego 2023 przez pasjonat_algorytmiki Pasjonat (19,540 p.)
czyli poprostu słabe testy były, które nie wychwyciły tego.

Podobne pytania

0 głosów
1 odpowiedź 156 wizyt
pytanie zadane 20 marca 2023 w Algorytmy przez pasjonat_algorytmiki Pasjonat (19,540 p.)
0 głosów
1 odpowiedź 222 wizyt

92,576 zapytań

141,426 odpowiedzi

319,650 komentarzy

61,961 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.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...