Open In App

Shortest path in an unweighted graph

Given an unweighted, undirected graph of V nodes and E edges, a source node S, and a destination node D, we need to find the shortest path from node S to node D in the graph.

Shortest-Path-in-an-Unweighted-Graph

Input: V = 8, E = 10, S = 0, D = 7, edges[][] = {{0, 1}, {1, 2}, {0, 3}, {3, 4}, {4, 7}, {3, 7}, {6, 7}, {4, 5}, {4, 6}, {5, 6}}
Output: 0 3 7
Explanation: The shortest path is 0 -> 3 -> 7.

Input: V = 8, E = 10, S = 2, D = 6, edges[][] = {{0, 1}, {1, 2}, {0, 3}, {3, 4}, {4, 7}, {3, 7}, {6, 7}, {4, 5}, {4, 6}, {5, 6}}
Output: 2 1 0 3 4 6
Explanation: The shortest path is 2 -> 1 -> 0 -> 3 - > 4 -> 6.

Approach:

The idea is to use a modified version of Breadth-First Search in which we keep storing the parent of a given vertex while doing the breadth-first search. We first initialize an array dist[0, 1, ...., v-1] such that dist[i] stores the distance of vertex i from the source vertex and array par[0, 1, ....., v-1] such that par[i] represents the parent of the vertex i in the breadth-first search starting from the source. 

Now we get the length of the path from source to any other vertex from array dist[], and for printing the path from source to any vertex we can use array par[].

Implementation:

C++
#include <bits/stdc++.h>
using namespace std;

// Modified bfs to store the parent of nodes along with the
// distance from source node
void bfs(vector<vector<int> >& graph, int S,
         vector<int>& par, vector<int>& dist)
{
    // queue to store the nodes in the order they are
    // visited
    queue<int> q;
    // Mark the distance of the source node as 0
    dist[S] = 0;
    // Push the source node to the queue
    q.push(S);

    // Iterate till the queue is not empty
    while (!q.empty()) {
        // Pop the node at the front of the queue
        int node = q.front();
        q.pop();

        // Explore all the neighbours of the current node
        for (int neighbour : graph[node]) {
            // Check if the neighbouring node is not visited
            if (dist[neighbour] == 1e9) {
                // Mark the current node as the parent of
                // the neighbouring node
                par[neighbour] = node;
                // Mark the distance of the neighbouring
                // node as distance of the current node + 1
                dist[neighbour] = dist[node] + 1;
                // Insert the neighbouring node to the queue
                q.push(neighbour);
            }
        }
    }
}

// Function to print the shortest distance between source
// vertex and destination vertex
void printShortestDistance(vector<vector<int> >& graph,
                           int S, int D, int V)
{
    // par[] array stores the parent of nodes
    vector<int> par(V, -1);

    // dist[] array stores distance of nodes from S
    vector<int> dist(V, 1e9);

    // function call to find the distance of all nodes and
    // their parent nodes
    bfs(graph, S, par, dist);

    if (dist[D] == 1e9) {
        cout << "Source and Destination are not connected";
        return;
    }

    // vector path stores the shortest path
    vector<int> path;
    int currentNode = D;
    path.push_back(D);
    while (par[currentNode] != -1) {
        path.push_back(par[currentNode]);
        currentNode = par[currentNode];
    }

    // printing path from source to destination
    for (int i = path.size() - 1; i >= 0; i--)
        cout << path[i] << " ";
}

// Driver program to test above functions
int main()
{
    // no. of vertices
    int V = 8, E = 10;
    // Source and Destination vertex
    int S = 2, D = 6;
    // edge list
    vector<vector<int> > edges
        = { { 0, 1 }, { 1, 2 }, { 0, 3 }, { 3, 4 },
            { 4, 7 }, { 3, 7 }, { 6, 7 }, { 4, 5 },
            { 4, 6 }, { 5, 6 } };

    // vector to store the graph as adjacency list
    vector<vector<int> > graph(V);
    for (auto edge : edges) {
        graph[edge[0]].push_back(edge[1]);
        graph[edge[1]].push_back(edge[0]);
    }

    printShortestDistance(graph, S, D, V);
    return 0;
}
Java
import java.util.*;

public class ShortestPathBFS {
    // Modified bfs to store the parent of nodes along with
    // the distance from the source node
    static void bfs(List<List<Integer> > graph, int S,
                    List<Integer> par, List<Integer> dist)
    {
        // Queue to store the nodes in the order they are
        // visited
        Queue<Integer> q = new LinkedList<>();
        // Mark the distance of the source node as 0
        dist.set(S, 0);
        // Push the source node to the queue
        q.add(S);

        // Iterate until the queue is not empty
        while (!q.isEmpty()) {
            // Pop the node at the front of the queue
            int node = q.poll();

            // Explore all the neighbors of the current node
            for (int neighbor : graph.get(node)) {
                // Check if the neighboring node is not
                // visited
                if (dist.get(neighbor)
                    == Integer.MAX_VALUE) {
                    // Mark the current node as the parent
                    // of the neighboring node
                    par.set(neighbor, node);
                    // Mark the distance of the neighboring
                    // node as the distance of the current
                    // node + 1
                    dist.set(neighbor, dist.get(node) + 1);
                    // Insert the neighboring node to the
                    // queue
                    q.add(neighbor);
                }
            }
        }
    }

    // Function to print the shortest distance between the
    // source vertex and destination vertex
    static void
    printShortestDistance(List<List<Integer> > graph, int S,
                          int D, int V)
    {
        // par[] array stores the parent of nodes
        List<Integer> par
            = new ArrayList<>(Collections.nCopies(V, -1));

        // dist[] array stores the distance of nodes from S
        List<Integer> dist = new ArrayList<>(
            Collections.nCopies(V, Integer.MAX_VALUE));

        // Function call to find the distance of all nodes
        // and their parent nodes
        bfs(graph, S, par, dist);

        if (dist.get(D) == Integer.MAX_VALUE) {
            System.out.println(
                "Source and Destination are not connected");
            return;
        }

        // List path stores the shortest path
        List<Integer> path = new ArrayList<>();
        int currentNode = D;
        path.add(D);
        while (par.get(currentNode) != -1) {
            path.add(par.get(currentNode));
            currentNode = par.get(currentNode);
        }

        // Printing path from source to destination
        for (int i = path.size() - 1; i >= 0; i--)
            System.out.print(path.get(i) + " ");
    }

    // Driver program to test above functions
    public static void main(String[] args)
    {
        // no. of vertices
        int V = 8;
        // Source and Destination vertex
        int S = 2, D = 6;
        // Edge list
        List<List<Integer> > edges = Arrays.asList(
            Arrays.asList(0, 1), Arrays.asList(1, 2),
            Arrays.asList(0, 3), Arrays.asList(3, 4),
            Arrays.asList(4, 7), Arrays.asList(3, 7),
            Arrays.asList(6, 7), Arrays.asList(4, 5),
            Arrays.asList(4, 6), Arrays.asList(5, 6));

        // List to store the graph as an adjacency list
        List<List<Integer> > graph = new ArrayList<>(V);
        for (int i = 0; i < V; i++) {
            graph.add(new ArrayList<>());
        }

        for (List<Integer> edge : edges) {
            graph.get(edge.get(0)).add(edge.get(1));
            graph.get(edge.get(1)).add(edge.get(0));
        }

        printShortestDistance(graph, S, D, V);
    }
}
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
using System.Linq;

public class GFG {
    // Modified BFS to store the parent of nodes along with
    // the distance from the source node
    static void BFS(List<List<int> > graph, int S,
                    List<int> par, List<int> dist)
    {
        // Queue to store the nodes in the order they are
        // visited
        Queue<int> q = new Queue<int>();
        // Mark the distance of the source node as 0
        dist[S] = 0;
        // Push the source node to the queue
        q.Enqueue(S);

        // Iterate until the queue is not empty
        while (q.Count > 0) {
            // Dequeue the node at the front of the queue
            int node = q.Dequeue();

            // Explore all the neighbors of the current node
            foreach(int neighbor in graph[node])
            {
                // Check if the neighboring node is not
                // visited
                if (dist[neighbor] == int.MaxValue) {
                    // Mark the current node as the parent
                    // of the neighboring node
                    par[neighbor] = node;
                    // Mark the distance of the neighboring
                    // node as the distance of the current
                    // node + 1
                    dist[neighbor] = dist[node] + 1;
                    // Insert the neighboring node to the
                    // queue
                    q.Enqueue(neighbor);
                }
            }
        }
    }

    // Function to print the shortest distance between the
    // source vertex and destination vertex
    static void
    PrintShortestDistance(List<List<int> > graph, int S,
                          int D, int V)
    {
        // par[] array stores the parent of nodes
        List<int> par = Enumerable.Repeat(-1, V).ToList();

        // dist[] array stores the distance of nodes from S
        List<int> dist
            = Enumerable.Repeat(int.MaxValue, V).ToList();

        // Function call to find the distance of all nodes
        // and their parent nodes
        BFS(graph, S, par, dist);

        if (dist[D] == int.MaxValue) {
            Console.WriteLine(
                "Source and Destination are not connected");
            return;
        }

        // List path stores the shortest path
        List<int> path = new List<int>();
        int currentNode = D;
        path.Add(D);
        while (par[currentNode] != -1) {
            path.Add(par[currentNode]);
            currentNode = par[currentNode];
        }

        // Printing path from source to destination
        for (int i = path.Count - 1; i >= 0; i--)
            Console.Write(path[i] + " ");
    }

    // Driver program to test above functions
    public static void Main(string[] args)
    {
        // no. of vertices
        int V = 8;
        // Source and Destination vertex
        int S = 2, D = 6;
        // Edge list
        List<List<int> > edges = new List<List<int> >{
            new List<int>{ 0, 1 }, new List<int>{ 1, 2 },
            new List<int>{ 0, 3 }, new List<int>{ 3, 4 },
            new List<int>{ 4, 7 }, new List<int>{ 3, 7 },
            new List<int>{ 6, 7 }, new List<int>{ 4, 5 },
            new List<int>{ 4, 6 }, new List<int>{ 5, 6 }
        };

        // List to store the graph as an adjacency list
        List<List<int> > graph
            = Enumerable.Range(0, V)
                  .Select(_ => new List<int>())
                  .ToList();

        foreach(List<int> edge in edges)
        {
            graph[edge[0]].Add(edge[1]);
            graph[edge[1]].Add(edge[0]);
        }

        PrintShortestDistance(graph, S, D, V);
    }
}
Javascript
class ShortestPathBFS {
    static bfs(graph, S, par, dist) {
        const q = [];
        dist[S] = 0;
        q.push(S);

        while (q.length > 0) {
            const node = q.shift();

            for (const neighbor of graph[node]) {
                if (dist[neighbor] === Infinity) {
                    par[neighbor] = node;
                    dist[neighbor] = dist[node] + 1;
                    q.push(neighbor);
                }
            }
        }
    }

    static printShortestDistance(graph, S, D, V) {
        const par = Array(V).fill(-1);
        const dist = Array(V).fill(Infinity);
        ShortestPathBFS.bfs(graph, S, par, dist);

        if (dist[D] === Infinity) {
            console.log("Source and Destination are not connected");
            return;
        }

        const path = [];
        let currentNode = D;
        path.push(D);
        while (par[currentNode] !== -1) {
            path.push(par[currentNode]);
            currentNode = par[currentNode];
        }

        // Concatenate the path elements into a single string
        const pathString = path.reverse().join(" ");
        console.log(pathString);
    }

    static main() {
        // no. of vertices
        const V = 8;
        // Source and Destination vertex
        const S = 2, D = 6;
        // Edge list
        const edges = [
            [0, 1], [1, 2], [0, 3], [3, 4],
            [4, 7], [3, 7], [6, 7], [4, 5],
            [4, 6], [5, 6]
        ];

        // Array to store the graph as an adjacency list
        const graph = Array.from({ length: V }, () => []);

        for (const edge of edges) {
            graph[edge[0]].push(edge[1]);
            graph[edge[1]].push(edge[0]);
        }

        ShortestPathBFS.printShortestDistance(graph, S, D, V);
    }
}

// Run the main function
ShortestPathBFS.main();
Python3
from collections import deque


def bfs(graph, S, par, dist):
    # Queue to store the nodes in the order they are visited
    q = deque()
    # Mark the distance of the source node as 0
    dist[S] = 0
    # Push the source node to the queue
    q.append(S)

    # Iterate until the queue is not empty
    while q:
        # Pop the node at the front of the queue
        node = q.popleft()

        # Explore all the neighbors of the current node
        for neighbor in graph[node]:
            # Check if the neighboring node is not visited
            if dist[neighbor] == float('inf'):
                # Mark the current node as the parent of the neighboring node
                par[neighbor] = node
                # Mark the distance of the neighboring node as the distance of the current node + 1
                dist[neighbor] = dist[node] + 1
                # Insert the neighboring node to the queue
                q.append(neighbor)


def print_shortest_distance(graph, S, D, V):
    # par[] array stores the parent of nodes
    par = [-1] * V

    # dist[] array stores the distance of nodes from S
    dist = [float('inf')] * V

    # Function call to find the distance of all nodes and their parent nodes
    bfs(graph, S, par, dist)

    if dist[D] == float('inf'):
        print("Source and Destination are not connected")
        return

    # List path stores the shortest path
    path = []
    current_node = D
    path.append(D)
    while par[current_node] != -1:
        path.append(par[current_node])
        current_node = par[current_node]

    # Printing path from source to destination
    for i in range(len(path) - 1, -1, -1):
        print(path[i], end=" ")


# Driver program to test above functions
if __name__ == "__main__":
    # no. of vertices
    V = 8
    # Source and Destination vertex
    S, D = 2, 6
    # Edge list
    edges = [
        [0, 1], [1, 2], [0, 3], [3, 4],
        [4, 7], [3, 7], [6, 7], [4, 5],
        [4, 6], [5, 6]
    ]

    # List to store the graph as an adjacency list
    graph = [[] for _ in range(V)]

    for edge in edges:
        graph[edge[0]].append(edge[1])
        graph[edge[1]].append(edge[0])

    print_shortest_distance(graph, S, D, V)


Time Complexity: O(V + E), where V is the number of vertices and E is the number of edges.
Auxiliary Space: O(V)

Article Tags :