Estou tentando resolver um problema gráfico (não é para trabalhos de casa, apenas para praticar minhas habilidades). Um DAG é dado, onde é o conjunto de vértices e as arestas. O gráfico é representado como uma lista de adjacência, portanto é um conjunto que contém todas as conexões de . A minha tarefa é encontrar quais vértices são acessíveis a partir de cada vértice . A solução que eu uso tem uma complexidade de , com fechamento transitivo, mas li que em um blog pode ser mais rápido, embora não tenha revelado como. Alguém poderia me dizer outra maneira (com melhor complexidade) de resolver o problema do fechamento transitivo em um DAG?V E A v v v ∈ V O ( V 3 )
algorithms
graph-theory
graphs
Rontogiannis Aristofanis
fonte
fonte
Respostas:
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,…,vn i<j vj vi
(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 nvn vn vn vn .
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 ivi vi vi vi .
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) n m∈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=64 i i i j cj ci
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.O O(n3)
fonte