O fato de nosso gráfico ser acíclico torna esse problema muito mais simples.
A ordenação topológica pode nos dar uma ordenação dos vértices modo que, se i < j , não há arestas de v j de volta a v i . Listamos os vértices de forma que todas as arestas em "avançem" em nossa lista.v1,v2,…,vni<jvjvi
(editado para corrigir a análise e fornecer um algoritmo um pouco mais rápido)
Agora apenas retrocedemos nesta lista, começando no último vértice . v n é fechamento transitivo é apenas em si. Adicione também v n ao fechamento transitivo de cada vértice com uma aresta para v nvnvnvnvn .
Para cada outro vértice , indo do final para trás, primeiro adicione v i ao seu próprio fechamento transitivo e, em seguida, adicione tudo no fechamento transitivo de v i ao fechamento transitivo de todos os vértices com uma aresta para v ivivivivi .
O tempo de funcionamento é , no pior caso, com n o número de vértices e m ∈ S ( N 2 ) o número de arestas. A ordenação topológica leva tempo O ( n + m ) . Em seguida, fazemos outro trabalho O ( m n ) na passagem para trás: À medida que retrocedemos na lista, para cada borda, temos que somar nO(n+m+nm)=O(n3)nm∈O(n2)O(n+m)O(mn)n vértices para o fechamento transitivo de alguém.
Observe que você pode obter uma boa aceleração de fator constante representando o fechamento transitivo de todos por matrizes de bits. Digamos que você tenha apenas ; então você deve usar um único int de 64 bits onde o bit i é 1 se i está no meu fechamento transitivo e 0 caso contrário. Em seguida, a parte em que adicionar tudo no i 's fechamento transitivo para j é é muito rápido: Nós apenas tomar c j | = c i . (Operação OR binária.)n=64iiijcjci
Para , você teria que mantê-los em matrizes e fazer alguma aritmética, mas seria muito mais rápido que um conjunto de objetos.n>64
Além disso, eu sei que o grande no pior dos casos ainda é O ( n 3 ) , mas para superar isso na prática você teria que ter algo muito mais complexo. Esse algoritmo também se sai muito bem em gráficos esparsos.OO(n3)