Skip to content

Commit 54526d8

Browse files
authored
Create README.md
1 parent f719891 commit 54526d8

File tree

1 file changed

+256
-0
lines changed
  • 23 - Graph Data Structure Problems/11 - Shortest Path in Undirected Graph

1 file changed

+256
-0
lines changed
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
<h1 align='center'>Shortest - Path in - Undirected - Graph</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [Shortest Path in Undirected Graph](https://www.geeksforgeeks.org/problems/shortest-path-in-undirected-graph-having-unit-distance/1)
6+
7+
![image](https://github.com/user-attachments/assets/d996625a-666e-430d-ae4f-8aa290548239)
8+
![image](https://github.com/user-attachments/assets/e9678f80-f2ef-40f3-ac14-5e7c3d3568f3)
9+
10+
## Problem Explanation
11+
We are given an **undirected graph** with `N` vertices and `M` edges. The graph is represented by a list of edges, where each edge connects two nodes (vertices) in the graph. Our task is to find the **shortest path** from a given source vertex `src` to all other vertices in the graph. The path length is measured by the number of edges traversed.
12+
13+
#### **Example 1:**
14+
Let's consider an example with 5 vertices (0 to 4) and the following edges:
15+
```
16+
Edges:
17+
0-1, 0-2, 1-3, 3-4
18+
```
19+
The graph looks like this:
20+
21+
```
22+
0 -- 1 -- 3 -- 4
23+
\
24+
2
25+
```
26+
27+
If the source vertex `src = 0`, the shortest paths from vertex 0 to all other vertices are:
28+
- `0 → 0` (distance 0)
29+
- `0 → 1` (distance 1)
30+
- `0 → 2` (distance 1)
31+
- `0 → 3` (distance 2)
32+
- `0 → 4` (distance 3)
33+
34+
The **shortest path** is the one that uses the least number of edges between the source and each target vertex.
35+
36+
#### **Approach:**
37+
1. **Graph Representation**: We can represent the graph using an adjacency list. Each node will have a list of neighboring nodes it is connected to by an edge.
38+
39+
2. **Breadth-First Search (BFS)**: To find the shortest path in an unweighted graph, we use **BFS**. This is because BFS explores all the nodes at the present depth level before moving on to nodes at the next depth level, guaranteeing the shortest path in an unweighted graph.
40+
41+
- **Why BFS?** BFS explores vertices level by level, ensuring that when we first reach a node, we do so via the shortest possible path.
42+
43+
3. **Steps to Approach**:
44+
- Initialize a distance array to store the shortest distance from the source to each vertex (set all distances to `-1` initially, except for the source which is set to 0).
45+
- Use a queue to help with BFS. Add the source node to the queue.
46+
- While the queue is not empty, process each node:
47+
- For each unvisited neighboring node, update its distance and mark it as visited, then add it to the queue.
48+
- Continue this process until all nodes have been visited.
49+
50+
**Key Observations**:
51+
- BFS ensures that the first time we visit a node, we do so via the shortest path.
52+
53+
#### **Example 2:**
54+
Consider a graph with 6 vertices and the following edges:
55+
```
56+
Edges:
57+
0-1, 0-2, 1-3, 3-4, 2-5
58+
```
59+
```
60+
0 -- 1 -- 3 -- 4
61+
\ \
62+
2 -- 5
63+
```
64+
If the source vertex is `src = 0`, the shortest distances from `0` to all other vertices would be:
65+
- `0 → 0` (distance 0)
66+
- `0 → 1` (distance 1)
67+
- `0 → 2` (distance 1)
68+
- `0 → 3` (distance 2)
69+
- `0 → 4` (distance 3)
70+
- `0 → 5` (distance 3)
71+
72+
## Problem Solution
73+
```cpp
74+
class Solution {
75+
public:
76+
vector<int> shortestPath(vector<vector<int>>& edges, int N, int M, int src) {
77+
// Step 1: Create an adjacency list to represent the graph
78+
vector<vector<int>> adj(N); // Adjacency list with N vertices
79+
// Build the adjacency list from the given edges
80+
for (int i = 0; i < M; i++) {
81+
int u = edges[i][0]; // Start vertex of the edge
82+
int v = edges[i][1]; // End vertex of the edge
83+
adj[u].push_back(v); // Add v as a neighbor of u
84+
adj[v].push_back(u); // Add u as a neighbor of v (since the graph is undirected)
85+
}
86+
87+
// Step 2: Initialize the distance array and visited array
88+
vector<int> distance(N, -1); // Distance array, initialized to -1 (unreachable)
89+
vector<bool> visited(N, false); // Visited array, initialized to false
90+
queue<int> q; // Queue to store vertices during BFS
91+
92+
// Step 3: Start BFS from the source node
93+
distance[src] = 0; // Distance to the source is 0
94+
visited[src] = true; // Mark the source as visited
95+
q.push(src); // Add the source node to the queue
96+
97+
// Step 4: Perform BFS to find the shortest path to all nodes
98+
while (!q.empty()) {
99+
int node = q.front(); // Get the front node from the queue
100+
q.pop(); // Remove the front node from the queue
101+
102+
// Step 5: Explore all neighbors of the current node
103+
for (int neighbor : adj[node]) {
104+
// If the neighbor hasn't been visited, update its distance and mark it as visited
105+
if (!visited[neighbor]) {
106+
visited[neighbor] = true; // Mark the neighbor as visited
107+
distance[neighbor] = distance[node] + 1; // Update the distance to the neighbor
108+
q.push(neighbor); // Add the neighbor to the queue for further exploration
109+
}
110+
}
111+
}
112+
113+
// Step 6: Return the final distance array
114+
return distance; // Return the array containing the shortest distances from src to all vertices
115+
}
116+
};
117+
118+
```
119+
120+
## Problem Solution Explanation
121+
Now, let’s break down the given code line by line.
122+
123+
```cpp
124+
class Solution {
125+
public:
126+
vector<int> shortestPath(vector<vector<int>>& edges, int N, int M, int src) {
127+
```
128+
- **Class Definition**: The solution is encapsulated in a class named `Solution`.
129+
- The method `shortestPath` takes:
130+
- `edges`: A vector of edges representing the graph.
131+
- `N`: The number of vertices.
132+
- `M`: The number of edges.
133+
- `src`: The source vertex from which we need to calculate the shortest paths to all other vertices.
134+
135+
```cpp
136+
vector<vector<int>> adj(N);
137+
```
138+
- **Adjacency List**: An adjacency list `adj` is created to represent the graph. It is a 2D vector where `adj[i]` stores all the nodes connected to vertex `i`.
139+
140+
```cpp
141+
for (int i = 0; i < M; i++) {
142+
int u = edges[i][0];
143+
int v = edges[i][1];
144+
adj[u].push_back(v);
145+
adj[v].push_back(u);
146+
}
147+
```
148+
- **Building the Graph**: Loop through each edge. For each edge `(u, v)`, add `v` to `adj[u]` and `u` to `adj[v]`. This creates an undirected graph by adding both directions for each edge.
149+
150+
```cpp
151+
vector<int> distance(N, -1);
152+
vector<bool> visited(N, false);
153+
queue<int> q;
154+
```
155+
- **Distance Array**: `distance[i]` stores the shortest distance from `src` to vertex `i`. It is initialized to `-1` to signify that no vertex has been visited yet.
156+
- **Visited Array**: `visited[i]` indicates whether vertex `i` has been visited. It is initially set to `false` for all vertices.
157+
- **Queue**: A queue `q` is initialized to help with BFS traversal.
158+
159+
```cpp
160+
distance[src] = 0;
161+
visited[src] = true;
162+
q.push(src);
163+
```
164+
- **Initialization**: The distance of the source vertex `src` is set to 0. We mark it as visited and add it to the queue.
165+
166+
```cpp
167+
while (!q.empty()) {
168+
int node = q.front();
169+
q.pop();
170+
```
171+
- **BFS Loop**: While the queue is not empty, we process the front node of the queue.
172+
173+
```cpp
174+
for (int neighbor : adj[node]) {
175+
if (!visited[neighbor]) {
176+
visited[neighbor] = true;
177+
distance[neighbor] = distance[node] + 1;
178+
q.push(neighbor);
179+
}
180+
}
181+
```
182+
- **Processing Neighbors**: For each unvisited neighbor of the current node:
183+
- Mark it as visited.
184+
- Set its distance to the current node's distance + 1.
185+
- Add the neighbor to the queue.
186+
187+
```cpp
188+
return distance;
189+
}
190+
};
191+
```
192+
- **Return Result**: After processing all nodes, the `distance` array is returned, which contains the shortest distances from the source to all other vertices.
193+
194+
### **Step 3: Example Walkthrough**
195+
196+
Let’s use the graph from Example 1:
197+
198+
```
199+
0 -- 1 -- 3 -- 4
200+
\
201+
2
202+
```
203+
204+
#### Input:
205+
```
206+
edges = {{0, 1}, {0, 2}, {1, 3}, {3, 4}}
207+
N = 5, M = 4, src = 0
208+
```
209+
210+
1. **Graph Representation**:
211+
The adjacency list `adj` will look like:
212+
```
213+
adj = {{1, 2}, {0, 3}, {0}, {1, 4}, {3}}
214+
```
215+
216+
2. **BFS Execution**:
217+
- `distance = {0, -1, -1, -1, -1}` (initial distances, with `src = 0` set to 0)
218+
- `visited = {true, false, false, false, false}` (only `src = 0` visited initially)
219+
- Start BFS:
220+
- **Process node 0**: Visit neighbors 1 and 2. Update their distances to 1.
221+
- **Process node 1**: Visit neighbor 3. Update its distance to 2.
222+
- **Process node 2**: Visit neighbor 5. Update its distance to 3.
223+
- **Process node 3**: Visit neighbor 4. Update its distance to 3.
224+
- **Process node 4**: End.
225+
226+
3. **Final Output**:
227+
```
228+
distance = {0, 1, 1, 2, 3}
229+
```
230+
231+
#### Output:
232+
```
233+
The shortest paths from vertex 0 to all other vertices are: 0 1 1 2 3
234+
```
235+
236+
### **Step 4: Time and Space Complexity**
237+
238+
#### **Time Complexity**:
239+
- **Graph Construction**: \(O(M)\), where `M` is the number of edges. This is because we process each edge once.
240+
- **BFS Traversal**: \(O(V + M)\), where `V` is the number of vertices and `M` is the number of edges. We process each vertex and each edge at most once.
241+
- **Total Time Complexity**: \(O(V + M)\)
242+
243+
#### **Space Complexity**:
244+
- **Adjacency List**: \(O(V + M)\) space is used for the adjacency list.
245+
- **Distance Array**: \(O(V)\)
246+
- **Visited Array**: \(O(V)\)
247+
- **Queue**: \(O(V)\) in the worst case.
248+
- **Total Space Complexity**: \(O(V + M)\)
249+
250+
### **Step 5: Additional Recommendations**
251+
1. **Handling Multiple Components**: If the graph has multiple disconnected components, BFS will only find the shortest path within the component containing the source. If you need to handle disconnected graphs, consider adding extra logic to
252+
253+
mark unreachable nodes or run BFS for each disconnected component.
254+
2. **Edge Cases**:
255+
- If there are no edges (`M = 0`), all distances except for the source should remain `-1`.
256+
- Ensure that `src` is always a valid vertex in the range `[0, N-1]`.

0 commit comments

Comments
 (0)