#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Graph {
public:
int V;
vector<vector<int>> adj;
Graph(int V) {
this->V = V;
adj.resize(V + 1);
}
void addEdge(int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
void bridgeUtil(int u, vector<bool> &visited, vector<int> &disc, vector<int> &low, int &time, int parent, vector<pair<int,int>> &bridges) {
visited[u] = true;
disc[u] = low[u] = ++time; // discovery and low time
for (int v : adj[u]) {
if (!visited[v]) {
bridgeUtil(v, visited, disc, low, time, u, bridges); // DFS
low[u] = min(low[u], low[v]); // update low[u]
if (low[v] > disc[u]) {
bridges.push_back({u, v}); // found bridge
}
} else if (v != parent) {
low[u] = min(low[u], disc[v]); // back edge
}
}
}
vector<pair<int,int>> findBridges() {
vector<bool> visited(V + 1, false);
vector<int> disc(V + 1, -1);
vector<int> low(V + 1, -1);
vector<pair<int,int>> bridges;
int time = 0;
for (int i = 1; i <= V; i++) {
if (!visited[i]) {
bridgeUtil(i, visited, disc, low, time, -1, bridges);
}
}
return bridges;
}
};
int main() {
Graph g(4);
g.addEdge(1, 2);
g.addEdge(2, 3);
g.addEdge(3, 1);
g.addEdge(2, 4);
vector<pair<int,int>> bridges = g.findBridges();
for (auto &edge : bridges) {
cout << edge.first << " - " << edge.second << "\n";
}
return 0;
}
disc[u] = low[u] = ++time; // discovery and low time
Assign discovery and low time when visiting node u
bridgeUtil(v, visited, disc, low, time, u, bridges); // DFS
Recursively visit unvisited neighbor v
low[u] = min(low[u], low[v]); // update low[u]
Update low[u] based on child's low value
if (low[v] > disc[u]) { bridges.push_back({u, v}); }
If child's low is greater than discovery of u, edge u-v is a bridge
else if (v != parent) { low[u] = min(low[u], disc[v]); }
Update low[u] for back edges to ancestors