Lema: Se existe uma aresta V -> Y e Y é também um sucessor indireto de V (por exemplo, V -> W -> + Y), então a aresta V -> Y é transitiva e não faz parte da raiz transitiva.
Método: Acompanhe o fechamento transitivo de cada vértice, trabalhando do terminal ao inicial, em ordem topológica inversa. O conjunto de sucessores indiretos de V é a união dos fechamentos transitivos dos sucessores imediatos de V. O fechamento transitivo de V é a união de seus sucessores indiretos e seus sucessores imediatos.
Algoritmo:
Initialise Visited as the empty set.
For each vertex V of G,
Invoke Visit(V).
Visit(V):
If V is not in Visited,
Add V to Visited,
Initialise Indirect as the empty set,
For each edge V -> W in G,
Invoke Visit(W),
Add Closure(W) to Indirect.
Set Closure(V) to Indirect.
For each edge V -> W in G,
Add W to Closure(V),
If W is in the set Indirect,
Delete the edge V -> W from G.
Isso pressupõe que você tenha alguma maneira eficiente de acompanhar conjuntos de vértices (por exemplo, mapas de bits), mas acho que essa suposição também é feita em outros algoritmos O (V + E).
Um efeito colateral potencialmente útil é que ele encontra o fechamento transitivo de cada vértice de G.