#include <iostream>
#include <vector>
#include <queue>
#include <limits>
#include <iomanip>
using namespace std;
// Definicja typu dla pary (waga, wierzchołek)
// Używamy 'long long' dla odległości, aby uniknąć przepełnienia w dużych grafach
const long long INF = numeric_limits<long long>::max();
typedef pair<long long, int> pii;
// Funkcja implementująca algorytm Dijkstry
vector<long long> dijkstra(int V, const vector<vector<pair<int, int>>>& adj, int start_node) {
// 1. Inicjalizacja:
// wektor odległości, początkowo nieskończoność dla wszystkich wierzchołków
vector<long long> dist(V, INF);
// kolejka priorytetowa przechowująca pary (odległość, wierzchołek)
// używamy greater, aby zaimplementować min-heap (kolejka priorytetowa dla minimalnych wartości)
priority_queue<pii, vector<pii>, greater<pii>> pq;
// Ustawienie odległości źródłowego wierzchołka na 0 i dodanie go do kolejki
dist[start_node] = 0;
pq.push({0, start_node});
// 2. Główna pętla algorytmu:
while (!pq.empty()) {
long long current_dist = pq.top().first;
int u = pq.top().second;
pq.pop();
// Jeśli odległość wyjęta z kolejki jest większa niż już znana najkrótsza odległość, pomijamy ten wierzchołek
// (może to być stary wpis z dłuższą drogą)
if (current_dist > dist[u]) {
continue;
}
// 3. Relaksacja krawędzi:
// Iteracja po wszystkich sąsiadach 'v' wierzchołka 'u'
for (auto& edge : adj[u]) {
int v = edge.first;
int weight = edge.second;
// Sprawdzamy, czy nowa droga przez 'u' do 'v' jest krótsza niż dotychczas znana
if (dist[u] + weight < dist[v]) {
// Aktualizujemy odległość do 'v'
dist[v] = dist[u] + weight;
// Dodajemy sąsiada do kolejki priorytetowej
pq.push({dist[v], v});
}
}
}
return dist;
}
int main() {
// Przykład użycia:
// Graf z 6 wierzchołkami (indeksy 0 do 5)
int V = 6;
// Lista sąsiedztwa: wektor wektorów par (sąsiad, waga krawędzi)
vector<vector<pair<int, int>>> adj(V);
// Dodawanie krawędzi: (źródło, cel, waga)
adj[0].push_back({1, 4});
adj[0].push_back({2, 2});
adj[1].push_back({2, 5});
adj[1].push_back({3, 10});
adj[2].push_back({4, 3});
adj[3].push_back({4, 4});
adj[4].push_back({5, 5});
adj[3].push_back({5, 11});
int start_node = 0;
// Wywołanie algorytmu Dijkstry
vector<long long> distances = dijkstra(V, adj, start_node);
// Wyświetlanie wyników
cout << "Najkrotsze odleglosci od wierzcholka startowego " << start_node << ":\n";
for (int i = 0; i < V; ++i) {
cout << "Do wierzcholka " << i << ": ";
if (distances[i] == INF) {
cout << "Niedostepny\n";
} else {
cout << distances[i] << "\n";
}
}
return 0;
}