Tarjan’s Cut-Vertex-Finding Algorithm is an algorithm that finds the cut vertices in an undirected graph in time and space.

Algorithm

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

Lemma

For any vertex in , is a cut vertex in iff, in , has a parent and there exists a child of such that there is no edge in connecting a vertex in the subtree rooted at to a vertex other than outside the subtree, or has no parent but has more than one child.

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 edge in .

Then, is a cut vertex iff, in , has a parent and there exists a child of such that , or has no parent but has more than one child.

  1. Apply the lemma to find the cut vertices.

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<int>> adj(n);
	for (int i = 0; i < m; i++) {
		adj[u[i]].push_back(v[i]);
		adj[v[i]].push_back(u[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 {
			int low = in[u] = t++, cnt = 0;
			for (int v : adj[u]) {
				if (in[v] == -1) {
					int clow = self(v);
					low = std::min(low, clow);
					cnt += clow == in[u];
				} else {
					low = std::min(low, in[v]);
				}
			}
			if (cnt > (u == i)) {
				res.push_back(u);
			}
 
			return low;
		})(i);
	}
 
	return res;
}