First, topologically sort the graph.
Now, starting from the beginning of the sorted array, start the width of the first search and try to find the desired "depth" (that is, the distance from the root) of each node. Since a node can have several parents, for node x , depth[x] is the maximum depth of all parents, plus one. We initialize depth for all nodes as -1 .
Now, bypassing bfs, when we encounter node p , we try to update the depth of all its children c , where depth[c] = max(depth[c],depth[p]+1) . Now there are two ways to detect a child using a shortcut.
- if
depth[p]+1 < depth[c] , this means that c has a parent with a greater depth than p . Therefore, edge p to c should be a shortcut. - if
depth[p]+1 > depth[c] and depth[c]!=-1 , this means that c has a parent with less depth than p . Therefore, p is the best parent, and the other parent of c must have a label with p .
In both cases, we mark c as problematic.
Now our goal is for each "problem" node x , we check all its parents, the depth of which should be depth[x]-1 . If any of them have a depth that is lower than this, she has a short belt with x that needs to be removed.
Since the graph can have several roots, we must have a variable to mark the visited nodes and repeat the above thing for all that remained inaccessible.
This sorts the problem with the yellow ring, because before we visit any node, all of its predecessors were already visited and correctly ranked. This is provided by topological sorting.
(Note: we can do this in just one pass. Instead of marking the problem nodes, we can maintain the parent variable for all nodes and remove the edge with the old parent whenever case 2 happens. Case 1 should be obvious)