Tarjan’s Bridge-Finding Algorithm is an algorithm that finds the bridges in an undirected graph in time and space.

Algorithm

  1. Find an arbitrary depth-first search forest of .

Lemma

Every bridge in corresponds to an edge in .

Lemma

For any edge in , let be the corresponding edge of in , then is a bridge in iff there is no non-tree edge in connecting a vertex in the subtree rooted at to a vertex outside the subtree.

Lemma

Let denote the entry time of during the depth-first search, denote the minimum of a vertex reachable from a vertex in the subtree rooted at via at most one non-tree edge in .

Then, for any edge in , corresponds to a bridge in iff .

  1. Apply the lemma to find the bridges.

This algorithm solves the problem in time and space.

std::vector<int> tarjan(int n, int m, const std::vector<int> &u, const std::vector<int> &v) {
	std::vector<std::vector<std::pair<int, int>>> adj(n);
	for (int i = 0; i < m; i++) {
		adj[u[i]].emplace_back(v[i], i);
		adj[v[i]].emplace_back(u[i], i);
	}
 
	std::vector in(n, -1);
	int t = 0;
	std::vector<int> res;
 
	for (int i = 0; i < n; i++) {
		if (~in[i]) {
			continue;
		}
 
		y_combinator([&](auto &&self, int u, int i) -> int {
			int low = in[u] = t++;
			for (auto [v, j] : adj[u]) {
				if (j == i) {
					continue;
				}
 
				if (in[v] == -1) {
					low = std::min(low, self(v, j));
				} else {
					low = std::min(low, in[v]);
				}
			}
			if (~i && low == in[u]) {
				res.push_back(i);
			}
 
			return low;
		})(i, -1);
	}
 
	return res;
}