Розбір
The number of vertices in the graph is large, so we use a priority queue to implement Dijkstra's algorithm.
Example
The graph given in the example, has the following form:
Algorithm implementation
Declare a constant for infinity.
#define INF 0x3F3F3F3F
Declare a structure for storing the weighted graph. Each element is a list of pairs (vertex, distance).
vector<vector<pair<int, int> > > g;
The function Dijkstra implements Dijkstra's algorithm starting from the vertex .
void Dijkstra(vector<vector<pair<int, int>>>& g, vector<int>& d, int start) {
Declare and initialize the priority queue . The elements of this queue will be pairs (distance from the source to the vertex, vertex). Thus, the vertex at the top of the queue will always be the one with the smallest distance from the source.
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; pq.push({0, start});
Initialize the array of shortest distances . The vertices of the graph are numbered from to .
d = vector<int>(n + 1, INF); d[start] = 0;
Continue the Dijkstra's algorithm until the queue is empty.
while (!pq.empty()) {
Extract the pair from the top of the priority queue.
pair<int, int> e = pq.top(); pq.pop(); int v = e.second; // node
Check if the vertex is a dummy vertex. If the distance to is greater than the already computed value , ignore this vertex.
if (e.first > d[v]) continue; // distance > d[v]
Iterate over all vertices adjacent to . The distance from to is .
for (auto edge: g[v]) { int to = edge.first; int cost = edge.second;
If the edge relaxes, update the value of and insert the pair into the queue.
if (d[v] + cost < d[to]) { d[to] = d[v] + cost; pq.push({d[to], to}); } } } }
The main part of the program. Read the input data.
scanf("%d %d %d %d", &n, &m, &start, &fin); g.resize(n + 1); for (i = 0; i < m; i++) {
Read the undirected edge with weight and add it to the graph .
scanf("%d %d %d", &b, &e, &w); g[b].push_back({e, w}); g[e].push_back({b, w}); }
Run Dijkstra's algorithm from the starting vertex .
Dijkstra(g, dist, start);
Print the shortest path distance . If is equal to infinity, then the path does not exist.
if (dist[fin] == INF) printf("-1\n"); else printf("%d\n", dist[fin]);
Algorithm implementation — edge structure
Declare a constant for infinity.
#define INF 0x3F3F3F3F
Declare an array of shortest distances .
vector<int> dist;
The structure stores information about an edge: the vertex it leads to and its weight .
struct edge { int node, dist; edge(int node, int dist) : node(node), dist(dist) {} };
The structure will also be used in the priority queue. The queue stores the vertices of the graph, where:
is the vertex number;
is the current distance from the start vertex to vertex .
The vertex at the top of the queue will be the one with the smallest value.
bool operator< (edge a, edge b) { return a.dist > b.dist; }
Declare the adjacency list of the graph.
vector<vector<edge> > g;
The function Dijkstra implements Dijkstra's algorithm starting from the vertex .
void Dijkstra(vector<vector<edge> > &g, vector<int> &d, int start) {
Declare and initialize the priority queue . The elements of this queue will be pairs (distance from the source to the vertex, vertex). Thus, the vertex at the top of the queue will always be the one with the smallest distance from the source.
priority_queue<edge> pq; pq.push(edge(start, 0));
Initialize the array of shortest distances . The vertices of the graph are numbered from to .
d = vector<int>(n + 1, INF); d[start] = 0;
Continue the Dijkstra's algorithm until the queue is empty.
while (!pq.empty()) {
Extract the pair from the top of the priority queue.
edge e = pq.top(); pq.pop(); int v = e.node;
Check if the vertex is a dummy vertex. If the distance to is greater than the already computed value , ignore this vertex.
if (e.dist > d[v]) continue;
Iterate over all vertices adjacent to . The distance from to is .
for (auto ed : g[v]) { int to = ed.node; int cost = ed.dist;
If the edge relaxes, update the value of and insert the pair into the queue.
if (d[v] + cost < d[to]) { d[to] = d[v] + cost; pq.push(edge(to, d[to])); } } } }
The main part of the program. Read the input data.
scanf("%d %d %d %d", &n, &m, &start, &fin); g.resize(n + 1); for (i = 0; i < m; i++) {
Read the undirected edge with weight and add it to the graph .
scanf("%d %d %d", &b, &e, &w); g[b].push_back(edge(e, w)); g[e].push_back(edge(b, w)); }
Run Dijkstra's algorithm from the starting vertex .
Dijkstra(g, dist, start);
Print the shortest path distance . If is equal to infinity, then the path does not exist.
if (dist[fin] == INF) printf("-1\n"); else printf("%d\n", dist[fin]);
Java implementation
import java.util.*; class Node implements Comparator<Node> { public int node, dist; Node() {} Node(int node, int dist) { this.node = node; this.dist = dist; } @Override public int compare(Node a, Node b) { return a.dist - b.dist; } }; public class Main { // Adjacency list representation of the edges static List<List<Node> > g; static int dist[]; static int INF = Integer.MAX_VALUE; static int n, m; static void dijkstra(int start) { PriorityQueue<Node> pq = new PriorityQueue<Node>(n+1, new Node()); for (int i = 0; i <= n; i++) dist[i] = Integer.MAX_VALUE; // Add source node to the priority queue pq.add(new Node(start, 0)); // Distance to the source is 0 dist[start] = 0; while(!pq.isEmpty()) { Node e = pq.poll(); int v = e.node; if (e.dist > dist[v]) continue; for(int j = 0; j < g.get(v).size(); j++) { int to = g.get(v).get(j).node; int cost = g.get(v).get(j).dist; if (dist[v] + cost < dist[to]) { dist[to] = dist[v] + cost; pq.add(new Node(to,dist[to])); } } } } public static void main(String[] args) { Scanner con = new Scanner(System.in); n = con.nextInt(); m = con.nextInt(); int start = con.nextInt(); int fin = con.nextInt(); g = new ArrayList<List<Node> >(); // Initialize list for every node for (int i = 0; i <= n; i++) { List<Node> item = new ArrayList<Node>(); g.add(item); } for(int i = 0; i < m; i++) { int b = con.nextInt(); int e = con.nextInt(); int w = con.nextInt(); g.get(b).add(new Node(e,w)); g.get(e).add(new Node(b,w)); } dist = new int[n+1]; dijkstra(start); if (dist[fin] == INF) System.out.println(-1); else System.out.println(dist[fin]); con.close(); } }
Python implementation
Import the priority queue.
from queue import PriorityQueue
Declare a constant for infinity .
INF = 10**9
The function Dijkstra implements Dijkstra's algorithm starting from the vertex .
def dijkstra(graph, dist, start):
Declare and initialize the priority queue . The elements of this queue will be pairs (distance from the source to the vertex, vertex). Thus, the vertex at the top of the queue will always be the one with the smallest distance from the source.
pq = PriorityQueue() pq.put((0, start))
Initialize the array of shortest distances . The vertices of the graph are numbered from to .
dist.extend([INF] * (n + 1)) dist[start] = 0
Continue the Dijkstra's algorithm until the queue is empty.
while not pq.empty():
Extract the pair from the top of the priority queue.
cur_dist, v = pq.get()
Check if the vertex is a dummy vertex. If the distance to is greater than the already computed value , ignore this vertex.
if cur_dist > dist[v]: continue
Iterate over all vertices adjacent to . The distance from to is .
for to, cost in graph[v]:
If the edge relaxes, update the value of and insert the pair into the queue.
if dist[v] + cost < dist[to]: dist[to] = dist[v] + cost pq.put((dist[to], to))
The main part of the program. Read the input data.
n, m = map(int, input().split()) start, fin = map(int, input().split()) g = [[] for _ in range(n + 1)] for _ in range(m):
Read the undirected edge with weight and add it to the graph .
b, e, w = map(int, input().split()) g[b].append((e, w)) g[e].append((b, w))
Initialize the list of shortest distances .
dist = []
Run Dijkstra's algorithm from the starting vertex .
dijkstra(g, dist, start)
Print the shortest path distance . If is equal to infinity, then the path does not exist.
if dist[fin] == INF: print("-1") else: print(dist[fin])