Course schedule (cycle detection)

Decide whether every course can be finished. A directed graph can be fully ordered only if it has no cycle.

Time O(V + E)Space O(V)Code C#
Watch it animatedStep through it, with the running line highlighted. Free with an account.

The idea

Colour every node white (unvisited). DFS from each white node, turning it grey (in progress) on entry and black (done) on exit. A grey node reached again means the recursion has looped back onto its own path, which is exactly a cycle. A black node is already proven safe and is never revisited.

Code

public static bool CanFinish(int n, Dictionary<char, List<char>> graph) {
    var state = new Dictionary<char, int>(); // 0 unvisited, 1 in progress, 2 done
    foreach (var u in graph.Keys)
        if (state.GetValueOrDefault(u) == 0 && HasCycle(u, graph, state))
            return false;
    return true;
}

static bool HasCycle(char u, Dictionary<char, List<char>> graph, Dictionary<char, int> state) {
    state[u] = 1; // in progress: sits on the current recursion path
    foreach (char v in graph[u]) {
        int s = state.GetValueOrDefault(v);
        if (s == 1) return true; // back edge to a grey node: a cycle
        if (s == 0 && HasCycle(v, graph, state)) return true;
    }
    state[u] = 2; // done: can never sit on a cycle
    return false;
}

Tips

In the .NET library

A back edge to a grey node is the one and only sign of a cycle in a directed graph. An edge to a black node is always safe, even if it looks like it "goes backwards" in the recursion.