Implement a parallel programming task using graphs
Last Updated :
23 Jul, 2025
Given a weighted directed graph with N nodes and M edges along with a source node S, use Parallel Programming to find the shortest distance from the source node S to all other nodes in the graph. The graph is given as an edge list edges[][] where for each index i, there is an edge from edges[i][0] to edges[i][1] with weight edges[i][2].
Example:
Input: N = 5, M = 8, S = 0, edges = {{0, 1, 2}, {0, 2, 4}, {1, 2, 1}, {1, 3, 7}, {2, 3, 3}, {2, 4, 5}, {3, 4, 2}, {4, 0, 6}}
Output: Shortest Distances from Vertex 0:
Vertex 0: 0, Vertex 1: 2, Vertex 2: 3, Vertex 3: 6, Vertex 4: 8
Approach:
This problem is typically solved using Dijkstra's algorithm for a sequential solution. However, the task is to parallelize this algorithm effectively to exploit the power of parallel computing. Below is the implementation for the above approach
Below is the implementation:
C++
#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;
int V;
vector<vector<pair<int, int> > > adj;
void addEdge(int u, int v, int w)
{
adj[u].push_back({ v, w });
}
void sequentialDijkstra(int src, vector<int>& dist)
{
// Initialize all the distance as infinite
dist.assign(V, INF);
dist[src] = 0;
// Create a set to store vertices with the minimum
// distance
vector<bool> processed(V, false);
// record the start time
auto start_time = chrono::high_resolution_clock::now();
// Find shortest path for all vertices
for (int count = 0; count < V - 1; ++count) {
int u = -1;
for (int i = 0; i < V; ++i) {
if (!processed[i]
&& (u == -1 || dist[i] < dist[u]))
u = i;
}
// Mark the picked vertex as processed
processed[u] = true;
// Update dist value of the adjacent vertices of the
// picked vertex.
for (const auto& edge : adj[u]) {
int v = edge.first;
int w = edge.second;
if (!processed[v] && dist[u] != INF
&& dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
}
}
}
// record the end time
auto end_time = chrono::high_resolution_clock::now();
auto duration
= chrono::duration_cast<chrono::microseconds>(
end_time - start_time);
// Print the sequential execution time
cout << "Sequential Dijkstra Execution Time: "
<< duration.count() << " microseconds" << endl;
}
void parallelDijkstra(int src, vector<int>& dist)
{
dist.assign(V, INF);
dist[src] = 0;
// Create a set to store vertices with the minimum
// distance
vector<bool> processed(V, false);
// Record the start time
auto start_time = chrono::high_resolution_clock::now();
// Find shortest path for all vertices
for (int count = 0; count < V - 1; ++count) {
int u = -1;
#pragma omp parallel for
for (int i = 0; i < V; ++i) {
if (!processed[i]
&& (u == -1 || dist[i] < dist[u]))
#pragma omp critical
u = (u == -1 || dist[i] < dist[u]) ? i : u;
}
// Mark the picked vertex as processed
processed[u] = true;
// Update dist value of the adjacent vertices of the
// picked vertex using Parallel Programming
#pragma omp parallel for
for (const auto& edge : adj[u]) {
int v = edge.first;
int w = edge.second;
if (!processed[v] && dist[u] != INF
&& dist[u] + w < dist[v]) {
#pragma omp critical
if (dist[u] != INF && dist[u] + w < dist[v])
dist[v] = dist[u] + w;
}
}
}
// Record the end time
auto end_time = chrono::high_resolution_clock::now();
auto duration
= chrono::duration_cast<chrono::microseconds>(
end_time - start_time);
// Print the parallel execution time
cout << "Parallel Dijkstra Execution Time: "
<< duration.count() << " microseconds"
<< "\n";
}
int main()
{
int S = 0;
V = 5;
adj.resize(V);
addEdge(0, 1, 2);
addEdge(0, 2, 4);
addEdge(1, 2, 1);
addEdge(1, 3, 7);
addEdge(2, 3, 3);
addEdge(3, 4, 5);
addEdge(3, 4, 2);
addEdge(4, 0, 6);
vector<int> dist(V, 1e9);
sequentialDijkstra(S, dist);
parallelDijkstra(S, dist);
cout << "Shortest distances from Vertex " << S << ":\n";
for (int i = 0; i < V; ++i) {
cout << "Vertex " << i << ": " << dist[i];
if (i != V - 1)
cout << ", ";
}
return 0;
}
Java
import java.util.*;
public class Main {
static final int INF = Integer.MAX_VALUE;
static int V;
static ArrayList<ArrayList<Pair>> adj = new ArrayList<>();
static class Pair {
int first, second;
Pair(int a, int b) {
first = a;
second = b;
}
}
// Function to add an edge to the adjacency list
static void addEdge(int u, int v, int w) {
adj.get(u).add(new Pair(v, w));
}
// Sequential implementation of Dijkstra's algorithm
static void sequentialDijkstra(int src, int[] dist) {
Arrays.fill(dist, INF);
dist[src] = 0;
boolean[] processed = new boolean[V];
long start_time = System.nanoTime();
// Iterate V-1 times to find shortest paths
for (int count = 0; count < V - 1; ++count) {
int u = -1;
// Find the vertex with the minimum distance value
for (int i = 0; i < V; ++i) {
if (!processed[i] && (u == -1 || dist[i] < dist[u]))
u = i;
}
processed[u] = true;
// Update the distance values of adjacent vertices
for (Pair edge : adj.get(u)) {
int v = edge.first;
int w = edge.second;
if (!processed[v] && dist[u] != INF && dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
}
}
}
long end_time = System.nanoTime();
long duration = (end_time - start_time) / 1000;
System.out.println("Sequential Dijkstra Execution Time: " + duration + " microseconds");
}
public static void main(String[] args) {
int S = 0; // Source vertex
V = 5; // Number of vertices
// Initialize adjacency list
for (int i = 0; i < V; i++)
adj.add(new ArrayList<>());
// Add edges to the graph
addEdge(0, 1, 2);
addEdge(0, 2, 4);
addEdge(1, 2, 1);
addEdge(1, 3, 7);
addEdge(2, 3, 3);
addEdge(3, 4, 5);
addEdge(3, 4, 2); // Note: This edge seems redundant (same as the previous one)
addEdge(4, 0, 6);
int[] dist = new int[V]; // Array to store shortest distances
sequentialDijkstra(S, dist);
System.out.println("Shortest distances from Vertex " + S + ":");
for (int i = 0; i < V; ++i) {
System.out.print("Vertex " + i + ": " + dist[i]);
if (i != V - 1)
System.out.print(", ");
}
}
}
Python3
# Python Implementation
import sys
import time
INF = sys.maxsize
def addEdge(adj, u, v, w):
adj[u].append((v, w))
def sequentialDijkstra(adj, src, dist):
V = len(adj)
dist[src] = 0
processed = [False] * V
start_time = time.time()
for count in range(V - 1):
u = -1
for i in range(V):
if not processed[i] and (u == -1 or dist[i] < dist[u]):
u = i
processed[u] = True
for edge in adj[u]:
v, w = edge
if not processed[v] and dist[u] != INF and dist[u] + w < dist[v]:
dist[v] = dist[u] + w
end_time = time.time()
duration = end_time - start_time
print("Sequential Dijkstra Execution Time: {} seconds".format(duration))
def parallelDijkstra(adj, src, dist):
V = len(adj)
dist[src] = 0
processed = [False] * V
start_time = time.time()
for count in range(V - 1):
u = -1
for i in range(V):
if not processed[i] and (u == -1 or dist[i] < dist[u]):
u = i
processed[u] = True
for edge in adj[u]:
v, w = edge
if not processed[v] and dist[u] != INF and dist[u] + w < dist[v]:
if dist[u] != INF and dist[u] + w < dist[v]:
dist[v] = dist[u] + w
end_time = time.time()
duration = end_time - start_time
print("Parallel Dijkstra Execution Time: {} seconds".format(duration))
if __name__ == "__main__":
S = 0
V = 5
adj = [[] for _ in range(V)]
addEdge(adj, 0, 1, 2)
addEdge(adj, 0, 2, 4)
addEdge(adj, 1, 2, 1)
addEdge(adj, 1, 3, 7)
addEdge(adj, 2, 3, 3)
addEdge(adj, 3, 4, 5)
addEdge(adj, 3, 4, 2)
addEdge(adj, 4, 0, 6)
dist = [INF] * V
sequentialDijkstra(adj, S, dist)
parallelDijkstra(adj, S, dist)
print("Shortest distances from Vertex {}: ".format(S), end="")
for i in range(V):
print("Vertex {}: {}".format(i, dist[i]), end="")
if i != V - 1:
print(", ", end="")
print()
# This code is contributed by Sakshi
C#
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
public class Program
{
// Maximum value for integer
const int INF = int.MaxValue;
// Function to add an edge into the adjacency list
static void AddEdge(List<(int, int)>[] adj, int u, int v, int w)
{
adj[u].Add((v, w));
}
// Function to find the shortest path from source vertex to all other vertices using Dijkstra's algorithm
static void SequentialDijkstra(List<(int, int)>[] adj, int src, int[] dist)
{
int V = adj.Length;
dist[src] = 0;
bool[] processed = new bool[V];
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int count = 0; count < V - 1; count++)
{
int u = -1;
for (int i = 0; i < V; i++)
{
if (!processed[i] && (u == -1 || dist[i] < dist[u]))
{
u = i;
}
}
processed[u] = true;
foreach (var edge in adj[u])
{
int v = edge.Item1, w = edge.Item2;
if (!processed[v] && dist[u] != INF && dist[u] + w < dist[v])
{
dist[v] = dist[u] + w;
}
}
}
stopwatch.Stop();
Console.WriteLine($"Sequential Dijkstra Execution Time: {stopwatch.Elapsed.TotalSeconds} seconds");
}
// Function to find the shortest path from source vertex to all other vertices using Dijkstra's algorithm in parallel
static void ParallelDijkstra(List<(int, int)>[] adj, int src, int[] dist)
{
int V = adj.Length;
dist[src] = 0;
bool[] processed = new bool[V];
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int count = 0; count < V - 1; count++)
{
int u = -1;
for (int i = 0; i < V; i++)
{
if (!processed[i] && (u == -1 || dist[i] < dist[u]))
{
u = i;
}
}
processed[u] = true;
foreach (var edge in adj[u])
{
int v = edge.Item1, w = edge.Item2;
if (!processed[v] && dist[u] != INF && dist[u] + w < dist[v])
{
dist[v] = dist[u] + w;
}
}
}
stopwatch.Stop();
Console.WriteLine($"Parallel Dijkstra Execution Time: {stopwatch.Elapsed.TotalSeconds} seconds");
}
public static void Main()
{
int S = 0;
int V = 5;
List<(int, int)>[] adj = new List<(int, int)>[V];
for (int i = 0; i < V; i++)
{
adj[i] = new List<(int, int)>();
}
// Adding edges to the graph
AddEdge(adj, 0, 1, 2);
AddEdge(adj, 0, 2, 4);
AddEdge(adj, 1, 2, 1);
AddEdge(adj, 1, 3, 7);
AddEdge(adj, 2, 3, 3);
AddEdge(adj, 3, 4, 5);
AddEdge(adj, 3, 4, 2);
AddEdge(adj, 4, 0, 6);
int[] dist = Enumerable.Repeat(INF, V).ToArray();
// Running Dijkstra's algorithm
SequentialDijkstra(adj, S, dist);
ParallelDijkstra(adj, S, dist);
// Printing the shortest distances
Console.Write($"Shortest distances from Vertex {S}: ");
for (int i = 0; i < V; i++)
{
Console.Write($"Vertex {i}: {dist[i]}");
if (i != V - 1)
{
Console.Write(", ");
}
}
Console.WriteLine();
}
}
JavaScript
class Pair {
constructor(a, b) {
this.first = a;
this.second = b;
}
}
// Function to add an edge to adjacency list
function addEdge(u, v, w, adj) {
adj[u].push(new Pair(v, w));
}
// Sequential implementation of the Dijkstra's algorithm
function GFG(src, dist, adj) {
const V = adj.length;
const INF = Number.MAX_SAFE_INTEGER;
// Initialize distance array with the infinity
dist.fill(INF);
dist[src] = 0;
const processed = new Array(V).fill(false);
const start_time = process.hrtime.bigint();
// Iterate V-1 times to find shortest paths
for (let count = 0; count < V - 1; ++count) {
let u = -1;
// Find the vertex with minimum distance value
for (let i = 0; i < V; ++i) {
if (!processed[i] && (u === -1 || dist[i] < dist[u]))
u = i;
}
processed[u] = true;
// Update the distance values of the adjacent vertices
for (const edge of adj[u]) {
const v = edge.first;
const w = edge.second;
if (!processed[v] && dist[u] !== INF && dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
}
}
}
const end_time = process.hrtime.bigint();
const duration = (end_time - start_time) / BigInt(1000);
console.log(`Sequential Dijkstra Execution Time: ${duration} microseconds`);
}
function main() {
const S = 0;
const V = 5;
// Initialize adjacency list
const adj = Array.from({ length: V }, () => []);
// Add edges to the graph
addEdge(0, 1, 2, adj);
addEdge(0, 2, 4, adj);
addEdge(1, 2, 1, adj);
addEdge(1, 3, 7, adj);
addEdge(2, 3, 3, adj);
addEdge(3, 4, 5, adj);
addEdge(3, 4, 2, adj);
addEdge(4, 0, 6, adj);
const dist = new Array(V);
GFG(S, dist, adj);
console.log(`Shortest distances from Vertex ${S}:`);
for (let i = 0; i < V; ++i) {
process.stdout.write(`Vertex ${i}: ${dist[i]}`);
if (i !== V - 1)
process.stdout.write(", ");
}
}
main();
OutputSequential Dijkstra Execution Time: 2 microseconds
Parallel Dijkstra Execution Time: 1 microseconds
Shortest distances from Vertex 0:
Vertex 0: 0, Vertex 1: 2, Vertex 2: 3, Vertex 3: 6, Vertex 4: 8
The time difference between parallel implementation and sequential implementation of graphs is 1 microsecond.
Similar Reads
Parallel Programming In R Parallel programming is a type of programming that involves dividing a large computational task into smaller, more manageable tasks that can be executed simultaneously. This approach can significantly speed up the execution time of complex computations and is particularly useful for data-intensive a
6 min read
Parallel Programming In R Parallel programming is a type of programming that involves dividing a large computational task into smaller, more manageable tasks that can be executed simultaneously. This approach can significantly speed up the execution time of complex computations and is particularly useful for data-intensive a
6 min read
Graph implementation using STL for competitive programming | Set 2 (Weighted graph) In Set 1, unweighted graph is discussed. In this post, weighted graph representation using STL is discussed. The implementation is for adjacency list representation of weighted graph. Undirected Weighted Graph We use two STL containers to represent graph: vector : A sequence container. Here we use i
7 min read
Parallel Programming in java In parallel programming, a complex problem is broken down into simpler subtasks that can be executed simultaneously by multiple computational resources. This method is widely used by larger organizations and companies to handle advanced projects, ensuring higher efficiency and faster turnaround time
3 min read
Implementation of Graph in C Graphs are versatile data structures used to model real-world problems like networks and maps, and in C, they are commonly implemented using adjacency matrices or lists with pointers and structures. This allows efficient traversal, insertion, and deletion using standard graph algorithms.Table of Con
5 min read
Implementation of Graph in C Graphs are versatile data structures used to model real-world problems like networks and maps, and in C, they are commonly implemented using adjacency matrices or lists with pointers and structures. This allows efficient traversal, insertion, and deletion using standard graph algorithms.Table of Con
5 min read