Given an undirected graph with V vertices numbered from 0 to V-1 and E edges, represented by 2d array edges[][], where edges[i]=[u,v] represents the edge between the vertices u and v. Determine whether a specific edge between two vertices (c, d) is a bridge.
Note:
- An edge is called a bridge if removing it increases the number of connected components of the graph.
- if there’s only one path between c and d (which is the edge itself), then that edge is a bridge.
Examples :
Input:c = 1, d = 2 Output: true Explanation: From the graph, we can clearly see that blocking the edge 1-2 will result in disconnection of the graph.
Hence, it is a Bridge.
Input:c = 0, d = 2 Output: false Explanation:
Blocking the edge between nodes 0 and 2 won't affect the connectivity of the graph. So, it's not a Bridge Edge. All the Bridge Edges in the graph are marked with a blue line in the above image.
Constraints:
1 ≤ V, E ≤ 105
0 ≤ c, d ≤ V-1
Approach 01:
-
C++
-
Python
#include <vector>
using namespace std;
class Solution {
public:
void dfs(int currentNode, vector<int> adjacencyList[], int source, int target, vector<int>& visited) {
visited[currentNode] = true;
for (int neighbor : adjacencyList[currentNode]) {
if (!visited[neighbor] && !(currentNode == source && neighbor == target)) {
dfs(neighbor, adjacencyList, source, target, visited);
}
}
}
bool isBridge(int vertexCount, vector<vector<int>>& edges, int source, int target) {
vector<int> adjacencyList[vertexCount];
for (const auto& edge : edges) {
int nodeU = edge[0];
int nodeV = edge[1];
adjacencyList[nodeU].push_back(nodeV);
adjacencyList[nodeV].push_back(nodeU);
}
vector<int> visited(vertexCount, 0);
dfs(source, adjacencyList, source, target, visited);
return !visited[target];
}
};
from typing import List
from collections import defaultdict
class Solution:
def dfs(self, currentNode: int, adjacencyList: List[List[int]], source: int, target: int, visited: List[bool]) -> None:
visited[currentNode] = True
for neighbor in adjacencyList[currentNode]:
if not visited[neighbor] and not (currentNode == source and neighbor == target):
self.dfs(neighbor, adjacencyList, source, target, visited)
def isBridge(self, vertexCount: int, edges: List[List[int]], source: int, target: int) -> bool:
adjacencyList = defaultdict(list)
for nodeU, nodeV in edges:
adjacencyList[nodeU].append(nodeV)
adjacencyList[nodeV].append(nodeU)
visited = [False] * vertexCount
self.dfs(source, adjacencyList, source, target, visited)
return not visited[target]
Time Complexity:
- Building the Graph:
Inserting all edges into the adjacency list takes \( O(E) \) time, where \( E \) is the number of edges.
- DFS Traversal:
The DFS may visit every vertex and edge once in the worst case, resulting in \( O(V + E) \) time.
- Total Time Complexity:
\( O(V + E) \), where \( V \) is the number of vertices and \( E \) is the number of edges.
Space Complexity:
- Adjacency List:
Stores all edges, taking \( O(V + E) \) space.
- Visited Array:
A boolean array of size \( V \), resulting in \( O(V) \) space.
- Recursion Stack (DFS):
In the worst case, DFS call stack can go as deep as \( O(V) \).
- Total Space Complexity:
\( O(V + E) \)
c = 1, d = 2
Output: true
Explanation: From the graph, we can clearly see that blocking the edge 1-2 will result in disconnection of the graph.
c = 0, d = 2
Output: false
Explanation:
Blocking the edge between nodes 0 and 2 won't affect the connectivity of the graph.
So, it's not a Bridge Edge. All the Bridge Edges in the graph are marked with a blue line in the above image.