Given a Undirected Graph of N vertices from 0 to N-1 and M edges and a 2D Integer array wdges, where there is a edge from vertex edge[i][0] to vertex edge[i][1] of unit weight.
Find the shortest path from the source to all other nodes in this graph. In this problem statement, we have assumed the source vertex to be â0â. If a vertex is unreachable from the source node, then return -1 for that vertex.
Input: n = 9, m = 10, edges = [[0,1],[0,3],[3,4],[4,5],[5, 6],[1,2],[2,6],[6,7],[7,8],[6,8]]
Output: 0 1 2 1 2 3 3 4 4
Explanation:
The above output array shows the shortest path to all
the nodes from the source vertex (0), Dist[0] = 0, Dist[1] = 1 , Dist[2] = 2 , …. Dist[8] = 4.Where Dist[node] is the shortest path between src and the node. For a node, if the value of Dist[node]= -1, then we conclude that the node is unreachable from the src node.
Input: n = 8, m = 10, edges =[[1,0],[2,1],[0,3],[3,7],[3,4],[7,4],[7,6],[4,5],[4,6],[6,5]]
Output: 0 1 2 1 2 3 3 2
Explanation:
The above output list shows the shortest path to all the nodes from the source vertex (0), Dist[0] = 0, Dist[1] = 1, Dist[2] = 2,.....Dist[7] = 2.
Input: n = 3, m = 1, edges = [[1,2]]
This problem was solved for directed graphs. One way is to convert the undirected graph into a directed one that requires converting every undirected edge between node a and node b to two directed edges:
#include <bits/stdc++.h>
using namespace std;
class Solution {
private:
// Function to perform BFS traversal
void bfs(int src, vector<int> adj[],
vector<int> &dist) {
// Distance of source node from itself is zero
dist[src] = 0;
// Queue to facilitate BFS traversal
queue<int> q;
// Adding source node to queue
q.push(src);
// Until the queue is empty
while(!q.empty()) {
// Get the node from queue
int node = q.front();
q.pop();
// Traverse all its neighbors
for(auto adjNode : adj[node]) {
// If a shorter distance is found
if(dist[node] + 1 < dist[adjNode]) {
// Update the distance
dist[adjNode] = 1 + dist[node];
// Add the node to the queue
q.push(adjNode);
}
}
}
}
public:
/* Function to get the shortest path
for every node from source node 0 */
vector<int> shortestPath(vector<vector<int>>& edges,
int N, int M){
// To store the graph
vector<int> adj[N];
// Add edges to the graph
for(auto it : edges) {
int u = it[0]; // first node
int v = it[1]; // second node
// Add the edge
adj[u].push_back(v);
adj[v].push_back(u);
}
// Distance array to store the shortest paths
vector <int> dist(N, 1e9);
// Start the BFS traversal from source node
bfs(0, adj, dist);
/* If a node is unreachable,
updating its distance to -1 */
for(int i = 0; i < N; i++) {
if (dist[i] == 1e9)
dist[i] = -1;
}
// Return the result
return dist;
}
};
int main() {
int N = 9, M = 10;
vector<vector<int>> edges = {
{0,1}, {0,3}, {3,4},
{4,5}, {5,6}, {1,2},
{2,6}, {6,7}, {7,8}, {6,8}
};
/* Creating an instance of
Solution class */
Solution sol;
/* Function call to determine order of
letters based on alien dictionary */
vector<int> ans = sol.shortestPath(edges, N, M);
// Output
cout << "The shortest distance of every node from source node is:\n";
for(int i=0; i < N; i++) {
cout << ans[i] << " ";
}
return 0;
}
import java.util.*;
public class Solution {
// Function to perform BFS traversal
private void bfs(int src, List<Integer>[] adj,
int[] dist) {
// Distance of source node from itself is zero
dist[src] = 0;
// Queue to facilitate BFS traversal
Queue<Integer> q = new LinkedList<>();
// Adding source node to queue
q.add(src);
// Until the queue is empty
while (!q.isEmpty()) {
// Get the node from queue
int node = q.poll();
// Traverse all its neighbors
for (int adjNode : adj[node]) {
// If a shorter distance is found
if (dist[node] + 1 < dist[adjNode]) {
// Update the distance
dist[adjNode] = 1 + dist[node];
// Add the node to the queue
q.add(adjNode);
}
}
}
}
/* Function to get the shortest path
for every node from source node 0 */
public int[] shortestPath(int[][] edges, int N, int M) {
// To store the graph
List<Integer>[] adj = new ArrayList[N];
for (int i = 0; i < N; i++) {
adj[i] = new ArrayList<>();
}
// Add edges to the graph
for (int[] edge : edges) {
int u = edge[0]; // first node
int v = edge[1]; // second node
// Add the edge
adj[u].add(v);
adj[v].add(u);
}
// Distance array to store the shortest paths
int[] dist = new int[N];
Arrays.fill(dist, Integer.MAX_VALUE);
// Start the BFS traversal from source node
bfs(0, adj, dist);
/* If a node is unreachable,
updating its distance to -1 */
for (int i = 0; i < N; i++) {
if (dist[i] == Integer.MAX_VALUE)
dist[i] = -1;
}
// Return the result
return dist;
}
public static void main(String[] args) {
int N = 9, M = 10;
int[][] edges = {
{0, 1}, {0, 3}, {3, 4},
{4, 5}, {5, 6}, {1, 2},
{2, 6}, {6, 7}, {7, 8}, {6, 8}
};
/* Creating an instance of
Solution class */
Solution sol = new Solution();
/* Function call to determine shortest paths */
int[] ans = sol.shortestPath(edges, N, M);
// Output
System.out.println("The shortest distance of every node from source node is:");
for (int i = 0; i < N; i++) {
System.out.print(ans[i] + " ");
}
}
}
from collections import deque
class Solution:
# Function to perform BFS traversal
def bfs(self, src, adj, dist):
# Distance of source node from itself is zero
dist[src] = 0
# Queue to facilitate BFS traversal
q = deque()
# Adding source node to queue
q.append(src)
# Until the queue is empty
while q:
# Get the node from queue
node = q.popleft()
# Traverse all its neighbors
for adjNode in adj[node]:
# If a shorter distance is found
if dist[node] + 1 < dist[adjNode]:
# Update the distance
dist[adjNode] = 1 + dist[node]
# Add the node to the queue
q.append(adjNode)
# Function to get the shortest path
# for every node from source node 0
def shortestPath(self, edges, N, M):
# To store the graph
adj = [[] for _ in range(N)]
# Add edges to the graph
for edge in edges:
u = edge[0] # first node
v = edge[1] # second node
# Add the edge
adj[u].append(v)
adj[v].append(u)
# Distance array to store the shortest paths
dist = [float('inf')] * N
# Start the BFS traversal from source node
self.bfs(0, adj, dist)
# If a node is unreachable,
# updating its distance to -1
for i in range(N):
if dist[i] == float('inf'):
dist[i] = -1
# Return the result
return dist
# Main function to execute the code
if __name__ == "__main__":
N = 9
M = 10
edges = [
[0, 1], [0, 3], [3, 4],
[4, 5], [5, 6], [1, 2],
[2, 6], [6, 7], [7, 8], [6, 8]
]
# Creating an instance of Solution class
sol = Solution()
# Function call to determine shortest paths
ans = sol.shortestPath(edges, N, M)
# Output
print("The shortest distance of every node from source node is:")
for i in range(N):
print(ans[i], end=" ")
class Solution {
// Function to perform BFS traversal
bfs(src, adj, dist) {
// Distance of source node from itself is zero
dist[src] = 0;
// Queue to facilitate BFS traversal
const q = [];
// Adding source node to queue
q.push(src);
// Until the queue is empty
while (q.length) {
// Get the node from queue
const node = q.shift();
// Traverse all its neighbors
adj[node].forEach(adjNode => {
// If a shorter distance is found
if (dist[node] + 1 < dist[adjNode]) {
// Update the distance
dist[adjNode] = 1 + dist[node];
// Add the node to the queue
q.push(adjNode);
}
});
}
}
/* Function to get the shortest path
for every node from source node 0 */
shortestPath(edges, N, M) {
// To store the graph
const adj = Array.from({ length: N }, () => []);
// Add edges to the graph
edges.forEach(edge => {
const u = edge[0]; // first node
const v = edge[1]; // second node
// Add the edge
adj[u].push(v);
adj[v].push(u);
});
// Distance array to store the shortest paths
const dist = Array(N).fill(Infinity);
// Start the BFS traversal from source node
this.bfs(0, adj, dist);
// If a node is unreachable,
// updating its distance to -1
for (let i = 0; i < N; i++) {
if (dist[i] === Infinity)
dist[i] = -1;
}
// Return the result
return dist;
}
}
// Main function to execute the code
const main = () => {
const N = 9;
const M = 10;
const edges = [
[0, 1], [0, 3], [3, 4],
[4, 5], [5, 6], [1, 2],
[2, 6], [6, 7], [7, 8], [6, 8]
];
// Creating an instance of Solution class
const sol = new Solution();
// Function call to determine shortest paths
const ans = sol.shortestPath(edges, N, M);
// Output
console.log("The shortest distance of every node from source node is:");
for (let i = 0; i < N; i++) {
process.stdout.write(ans[i] + " ");
}
};
main();
Time Complexity: O(N+M)
Space Complexity: O(N+M)
Q: Can this approach handle graphs with negative weights?
A: Yes, since there are no cycles, negative weights do not create infinite loops like in Dijkstra’s algorithm. However, if the graph had cycles, we would need Bellman-Ford to detect negative weight cycles.
Q: How does this compare to Dijkstra’s Algorithm?
A: Dijkstra’s Algorithm is best for graphs with arbitrary weights and cycles, using a priority queue (O(N + M log N)). Topological sorting for DAGs works in O(N + M), which is faster for acyclic graphs.
Q: What if we needed to find the longest path instead?
A: Convert the problem into a longest path problem by negating all weights, applying the same topological sorting approach, and then reversing the result.
Q: How would this solution change if the graph was not a DAG?
A: If cycles exist, we cannot use topological sorting. Instead, we must use Dijkstra’s Algorithm (if all weights are non-negative) or Bellman-Ford (if negative weights exist).