Tarjan’s Bridge-Finding Algorithm is an algorithm that finds the bridges in an undirected graph in time and space.
Algorithm
- 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 .
- 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;
}