Generalize DFS, make use of it in other algorithms

I appreciate Tayllan's work, but current version of Depth-First Search makes it very hard to reuse this code in other algorithms, because all it does is computing finishing times of nodes and there is nothing user can do about it. Moreover, concerns about finishing times complicate the DFS code itself and make it less clear.

This version supports custom callbacks, which can control any decision DFS makes along the way and can be easily extended later on.