#include // ^ "magický include", který includuje většinu standardních hlaviček using namespace std; const double inf = 1e20; // dostatečně velké "nekonečno", lze zvětšit dle potřeby /* Formát vstupu: na prvním řádu čísla N, M, E, A, B oddělená mezerou, kde N je * počet stanic, M počet tunelů, E kapacita baterie, A a B počáteční a cílová * stanice. Na dalších M řádcích popisy hran: číslo počátečního a koncového * vrcholu (od 1 do N) a délka tunelu. */ int main(void) { /**** Načtení vstupu ****/ int n, m; // počet vrcholů a hran int A, B; double E; cin >> n >> m >> E >> A >> B; A--, B--; // chceme číslovat od nuly vector>> G(n); // Graf reprezentovaný seznamem sousedů, hranu ukládáme jako dvojici (sousední vrchol, délka) for (int i = 0; i < m; i++) { int a, b; double delka; cin >> a >> b >> delka; a--, b--; G[a].push_back({b, delka}); G[b].push_back({a, delka}); } /**** Dijkstrův algoritmus ****/ // Odmocníme délky tunelů: for (int v = 0; v < n; v++) for (auto &u : G[v]) u.second = sqrt(u.second); // Binární vyhledávací strom, který bude plnit roli haldy schopné upravovat // libovolné vrcholy. Primárně řadí podle odmocněné vzdálenosti, sekundárně // (což nás nezajímá) podle čísla vrcholu set> q; // Pro každý vrchol si pamatujeme součet (odmocněných) délek hran na // aktuálně nejlepší cestě do něj, na začátku všude nekonečno, kromě do A vector best(n, inf); best[A] = 0; // Pro každý vrchol si pamatujeme, odkud jsme ho zlepšili, z těchto hodnot // pak na konci sestrojíme nejlepší cestu. -1 značí "nenavštíveno" / "je // počáteční" vector> from(n, {-1, -1}); q.insert({0, A}); while (q.size()) { // vezmeme nejmenší záznam a odstraníme ho auto a = *q.begin(); q.erase(a); int v = a.second; // Skončíme v momentě, kdy máme spočítané B (to nás ale v průměru // zrychlí jen konstanta-krát) if (v == B) break; for (auto e : G[v]) { // pro všechny hrany z v int u = e.first; double w = e.second; double aktualni = best[u]; double nova = best[v] + w; // pokud jde vrchol u zlepšit z vrcholu v if (nova < aktualni) { // odstraníme z "haldy" a přidáme znova s lepší hodnotou q.erase({best[u], u}); best[u] = nova; q.insert({best[u], u}); // poznačíme, že nejlepší cestu do u jsme získali z v from[u] = {w, v}; } } } if (from[B].second == -1) { cout << "Neexistuje cesta ze startu do cíle!"; return 0; } vector> cesta; // skáčeme pozpátku, dokud nedoskáčeme do A for (int v = B; v != A; v = from[v].second) cesta.push_back(from[v]); // cestu obrátíme reverse(cesta.begin(), cesta.end()); cout << "Nejvýhodnější cesta: "; for (auto v : cesta) cout << v.second + 1 << " "; // indexujeme od jedničky // B jsme přeskočili, protože jsme začali s from[B] cout << B + 1 << "\n"; double S = 0; // součet odmocnin délek for (auto v : cesta) S += v.first; double celkem_cas = 0; cout << "Rychlosti průjezdů:"; for (auto v : cesta) { double rychlost = E * v.first / S; double delka = v.first * v.first; double cas = delka / rychlost; celkem_cas += cas; cout << " " << rychlost; } cout << "\n"; cout << "Celkový čas: " << celkem_cas << "\n"; }