Skip to content

Commit 9add185

Browse files
Merge pull request Pradeepsingh61#350 from Abdullah-Shah-26/feature/tarjans_algorithm
Added Tarjan's algorithm (bridges) to CPP/algorithms/graph_algorithms
2 parents 598ff80 + cf0c2b4 commit 9add185

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
// Tarjan's Algorithm — Find Bridges in an Undirected Graph
2+
// Problem : Find all bridges (critical edges) in a graph
3+
// Approach: DFS with discovery times (disc) and low-link values (low)
4+
// Complexity Analysis:
5+
// Time : O(V + E)
6+
// Space : O(V + E)
7+
8+
#include <iostream>
9+
#include <vector>
10+
#include <algorithm> // for min
11+
using namespace std;
12+
13+
class TarjanBridges
14+
{
15+
int V;
16+
vector<int> disc, low; // discovery time and low-link values
17+
vector<int> visited; // visited markers
18+
int timer; // global discovery timer
19+
20+
void dfs(int u, int parent, vector<vector<int>> &adj, vector<pair<int, int>> &bridges)
21+
{
22+
visited[u] = 1;
23+
disc[u] = low[u] = timer++;
24+
25+
for (int v : adj[u])
26+
{
27+
if (v == parent)
28+
continue; // ignore parent edge
29+
30+
if (!visited[v])
31+
{
32+
dfs(v, u, adj, bridges);
33+
low[u] = min(low[u], low[v]);
34+
35+
// Bridge condition
36+
if (low[v] > disc[u])
37+
{
38+
bridges.push_back({u, v});
39+
}
40+
}
41+
else
42+
{
43+
// back edge
44+
low[u] = min(low[u], disc[v]);
45+
}
46+
}
47+
}
48+
49+
public:
50+
TarjanBridges(int n)
51+
{
52+
V = n;
53+
disc.assign(V, -1);
54+
low.assign(V, -1);
55+
visited.assign(V, 0);
56+
timer = 0;
57+
}
58+
59+
vector<pair<int, int>> findBridges(vector<vector<int>> &edges)
60+
{
61+
// Build adjacency list: O(V + E) space
62+
vector<vector<int>> adj(V);
63+
for (auto &e : edges)
64+
{
65+
int u = e[0], v = e[1];
66+
adj[u].push_back(v);
67+
adj[v].push_back(u);
68+
}
69+
70+
vector<pair<int, int>> bridges;
71+
// Run DFS from each component root: O(V + E) time
72+
for (int i = 0; i < V; i++)
73+
{
74+
if (!visited[i])
75+
{
76+
dfs(i, -1, adj, bridges);
77+
}
78+
}
79+
return bridges;
80+
}
81+
};
82+
83+
int main()
84+
{
85+
ios::sync_with_stdio(false);
86+
cin.tie(nullptr);
87+
88+
int V, E;
89+
cin >> V >> E;
90+
91+
vector<vector<int>> edges;
92+
edges.reserve(E);
93+
for (int i = 0; i < E; i++)
94+
{
95+
int u, v;
96+
cin >> u >> v;
97+
edges.push_back({u, v});
98+
}
99+
100+
TarjanBridges solver(V);
101+
vector<pair<int, int>> bridges = solver.findBridges(edges);
102+
103+
cout << "Bridges in graph:\n";
104+
for (auto &b : bridges)
105+
{
106+
cout << b.first << " - " << b.second << "\n";
107+
}
108+
109+
return 0;
110+
}
111+
112+
/*
113+
🔹 Visualization Example
114+
115+
Graph:
116+
Vertices: 0,1,2,3,4
117+
Edges:
118+
0-1, 1-2, 2-0, 1-3, 3-4
119+
120+
ASCII:
121+
0
122+
/ \
123+
1---2
124+
|
125+
3
126+
|
127+
4
128+
129+
Step 1: DFS Traversal (with discovery time disc and low-link low)
130+
- Start at node 0, timer=0
131+
- DFS path: 0 -> 1 -> 2 -> 0 (back edge), then 1 -> 3 -> 4
132+
133+
Node states:
134+
Node disc low
135+
0 0 0
136+
1 1 1
137+
2 2 0 (back edge to 0)
138+
3 3 3
139+
4 4 4
140+
141+
Step 2: Bridge Detection
142+
- Edge 1-3: low[3] = 3 > disc[1] = 1 → Bridge
143+
- Edge 3-4: low[4] = 4 > disc[3] = 3 → Bridge
144+
- Other edges (0-1, 0-2, 1-2) form cycles → Not bridges
145+
146+
Step 3: Output
147+
Bridges = {(1,3), (3,4)}
148+
149+
🔹 Complexity Explanation:
150+
151+
Time Complexity O(V + E):
152+
- Each vertex is visited exactly once in DFS → O(V)
153+
- Each edge is traversed exactly twice (once per endpoint) → O(E)
154+
- So total = O(V + E)
155+
156+
Space Complexity O(V + E):
157+
- Adjacency list stores each edge twice → O(V + E)
158+
- Arrays disc, low, visited → O(V)
159+
- Recursion stack in DFS → O(V) in worst case
160+
- Total = O(V + E)
161+
*/

0 commit comments

Comments
 (0)