We use one more simple data structure, a stack L (represented as a list) which we use to identify the subtree rooted at a vertex. We simply push each new vertex onto L as we visit it; then when we have finished visiting a vertex, its subtree will be everything pushed after it onto L. If v is a head, and we've already deleted the other heads in that subtree, the remaining vertices left on L will be exactly the component [v].
We are now ready to describe the actual algorithm. It simply performs a DFS, keeping track of the low and dfsnum values defined above, using them to identify heads of components, and when finding a head deleting the whole component from the graph, using L to find the vertices of the component.
DFS(G)
{
make a new vertex x with edges x->v for all v
initialize a counter N to zero
initialize list L to empty
build directed tree T, initially a single vertex {x}
visit(x)
}
visit(p)
{
add p to L
dfsnum(p) = N
increment N
low(p) = dfsnum(p)
for each edge p->q
if q is not already in T
{
add p->q to T
visit(q)
low(p) = min(low(p), low(q))
} else low(p) = min(low(p), dfsnum(q))
if low(p)=dfsnum(p)
{
output "component:"
repeat
remove last element v from L
output v
remove v from G
until v=p
}
}