SlideShare ist ein Scribd-Unternehmen logo
1 von 43
Downloaden Sie, um offline zu lesen
Universidade Federal de Ouro Preto


Instituto de Ciências Exatas e Biológicas


     Departamento de Computação




   TEORIA DOS GRAFOS
    Primeiro Trabalho Prático
       Caminhos Mínimos




     Johnnatan Messias P. Afonso
           Kayran dos Santos
           Vítor Mangaravite


  Professor - Haroldo Gambini Santos




              Ouro Preto
         25 de outubro de 2010
Sumário
1 Introdução                                                                             1
  1.1   Considerações iniciais . . . . . . . . . . . . . . . . . . . . . . . . . . .      1
  1.2   Especicações da máquina . . . . . . . . . . . . . . . . . . . . . . . .          1
  1.3   Especicação do problema       . . . . . . . . . . . . . . . . . . . . . . . .    1
        1.3.1   Material a ser entregue . . . . . . . . . . . . . . . . . . . . . .       1
        1.3.2   Documentação impressa incluindo . . . . . . . . . . . . . . . .           2
        1.3.3   Regras de Implementação        . . . . . . . . . . . . . . . . . . . .    2
        1.3.4   Problemas Teste      . . . . . . . . . . . . . . . . . . . . . . . . .    2
        1.3.5   Formato de Entrada e Saída e Parâmetros          . . . . . . . . . . .    3
  1.4   Dijkstra   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    3
        1.4.1   Heaps    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    4
        1.4.2   Aplicação do Algoritmo       . . . . . . . . . . . . . . . . . . . . .   5
        1.4.3   Versão Preliminar x Final      . . . . . . . . . . . . . . . . . . . .    5
  1.5   Floyd-Warshall     . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    5
        1.5.1   Aplicação do Algoritmo       . . . . . . . . . . . . . . . . . . . . .   6
        1.5.2   Versão Preliminar x Final      . . . . . . . . . . . . . . . . . . . .    6


2 Algoritmo e estruturas de dados                                                        7
  2.1   Grafo do Dijkstra . . . . . . . . . . . . . . . . . . . . . . . . . . . . .       7
        2.1.1   Função CriaGrafoPorNome . . . . . . . . . . . . . . . . . . . .           7
        2.1.2   Função ConstruindoLista . . . . . . . . . . . . . . . . . . . . .         8
        2.1.3   Função AddInteração . . . . . . . . . . . . . . . . . . . . . . .         9
  2.2   Heap Binária     . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    9
        2.2.1   Inicialização da heap    . . . . . . . . . . . . . . . . . . . . . . .   10
        2.2.2   Remove menor       . . . . . . . . . . . . . . . . . . . . . . . . . .   11
        2.2.3   Diminui    . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   11
        2.2.4   Tamanho      . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   12
  2.3   Dijkstra   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   12
        2.3.1   Função Dijkstra . . . . . . . . . . . . . . . . . . . . . . . . . .      12
        2.3.2   Função DijkstraP . . . . . . . . . . . . . . . . . . . . . . . . .       13
        2.3.3   Função Main para o Dijkstra . . . . . . . . . . . . . . . . . . .        14
  2.4   Grafo do Floyd-Warshall . . . . . . . . . . . . . . . . . . . . . . . . .        15
        2.4.1   Função CriaGrafoPorNome . . . . . . . . . . . . . . . . . . . .          16
        2.4.2   Função alocaMatriz . . . . . . . . . . . . . . . . . . . . . . . .       17
        2.4.3   Função iniciaMatriz . . . . . . . . . . . . . . . . . . . . . . . .      19
        2.4.4   Função iniciaPred . . . . . . . . . . . . . . . . . . . . . . . . .      19
  2.5   Floyd-Warshall     . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   20
        2.5.1   Função oydP . . . . . . . . . . . . . . . . . . . . . . . . . . .       20
        2.5.2   Função oyd . . . . . . . . . . . . . . . . . . . . . . . . . . . .      21
        2.5.3   Função oydPNeg . . . . . . . . . . . . . . . . . . . . . . . . .        21
        2.5.4   Função oydNeg       . . . . . . . . . . . . . . . . . . . . . . . . .   23
        2.5.5   Função imprimirsalvar      . . . . . . . . . . . . . . . . . . . . . .   23
        2.5.6   Função mainF . . . . . . . . . . . . . . . . . . . . . . . . . . .       24




                                           2
3 Testes                                                                                 27
  3.1   Exemplo de teste para o Floyd-Warshall         . . . . . . . . . . . . . . . .   27
        3.1.1   Grafo com Peso Positivo . . . . . . . . . . . . . . . . . . . . .        27
        3.1.2   Grafo com Peso Negativo . . . . . . . . . . . . . . . . . . . . .        29
  3.2   Testes em massa      . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   31
        3.2.1   Floyd-Warshall     . . . . . . . . . . . . . . . . . . . . . . . . . .   31
        3.2.2   Dijkstra   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   34


4 Conclusão                                                                              36

Lista de Figuras
  1     Figura Repres. Alocação Matriz . . . . . . . . . . . . . . . . . . . . .         18
  2     Figura Grafo com Peso Positivos        . . . . . . . . . . . . . . . . . . . .   27
  3     Figura Matriz Dist     . . . . . . . . . . . . . . . . . . . . . . . . . . . .   27
  4     Figura Matriz Pred . . . . . . . . . . . . . . . . . . . . . . . . . . . .       28
  5     Figura Exemplo de Caminho . . . . . . . . . . . . . . . . . . . . . . .          28
  6     Figura Grafo com Peso Negativo . . . . . . . . . . . . . . . . . . . . .         29
  7     Figura Matriz Dist     . . . . . . . . . . . . . . . . . . . . . . . . . . . .   29
  8     Figura Matriz Pred . . . . . . . . . . . . . . . . . . . . . . . . . . . .       30
  9     Figura Exemplo de Caminho Neg          . . . . . . . . . . . . . . . . . . . .   30
  10    Graco para Floyd-Warshall sobre o grafo rg300_768 . . . . . . . . .             31
  11    Graco para Floyd-Warshall sobre o grafo rg300_4730            . . . . . . . .   32
  12    Graco para Floyd-Warshall sobre o grafo comp-2007-2-22c . . . . . .             33
  13    Graco para Dijkstra sobre o grafo rome99c         . . . . . . . . . . . . . .   34
  14    Graco para Dijkstra sobre o grafo USA-road-d-NYc            . . . . . . . . .   35




Lista de Programas
  1     Algoritmo Floyd Warshall C . . . . . . . . . . . . . . . . . . . . . . .          5
  2     TAD Grafo     . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     7
  3     Função CriaGrafoPorNome para o dijkstra . . . . . . . . . . . . . . .             7
  4     Função ConstruindoLista . . . . . . . . . . . . . . . . . . . . . . . . .         8
  5     Função ConstruindoLista . . . . . . . . . . . . . . . . . . . . . . . . .         9
  6     TAD Grafo     . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     9
  7     Criação da heap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      10
  8     Inicialização da heap    . . . . . . . . . . . . . . . . . . . . . . . . . . .   10
  9     Remove Menor       . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   11
  10    Decrementa Chave       . . . . . . . . . . . . . . . . . . . . . . . . . . . .   11
  11    Tamanho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      12
  12    Fijkstra sem Impressão . . . . . . . . . . . . . . . . . . . . . . . . . .       12
  13    Dijkstra com Impressão . . . . . . . . . . . . . . . . . . . . . . . . . .       13
  14    Programa principal do Dijkstra       . . . . . . . . . . . . . . . . . . . . .   14
  15    TAD Grafo     . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    16
  16    Função criagrafopornome . . . . . . . . . . . . . . . . . . . . . . . . .        16
  17    Função alocaMatriz . . . . . . . . . . . . . . . . . . . . . . . . . . . .       19
  18    Função iniciamatriz . . . . . . . . . . . . . . . . . . . . . . . . . . . .      19




                                           3
19   Função iniciaPred . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     19
  20   Função oydP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      20
  21   Função oyd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     21
  22   Função oydPNeg . . . . . . . . . . . . . . . . . . . . . . . . . . . . .       22
  23   Função oydNeg      . . . . . . . . . . . . . . . . . . . . . . . . . . . . .   23
  24   Função imprimirsalvar     . . . . . . . . . . . . . . . . . . . . . . . . . .   23
  25   Função mainF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      24
  26   Programa de Teste     . . . . . . . . . . . . . . . . . . . . . . . . . . . .   38




Lista de Tabelas
  1    Instâncias de teste e algoritmos a executar     . . . . . . . . . . . . . . .    2




                                         4
1       Introdução
    A computação tem como base a resolução de problemas que até então não havia
soluções disponíveis bem como para soluções rápidas para o mesmo problema.
    Assim, cabe ao Cientista da Computação identicar soluções para a resolução
dos problemas, principalmente, tornando-os otimizados e rápidos.               Através desses
conceitos coube ao grupo utilizar os conceitos de Teoria dos Grafos para a modelagem
do trabalho.
    Na teoria de grafos, o problema do caminho mínimo consiste na minimização do
custo de travessia de um grafo entre dois nós (ou vértices). Custo este dado pela
soma dos pesos de cada aresta percorrida.
    Formalmente, dado um grafo valorado (ou seja, um conjunto            V   de vértices, um
conjunto    A   de arestas e uma função de peso     f : A → R) e, dado   qualquer elemento
v ∈V,    encontrar um caminho    P   de   v para  cada v ∈ V tal que     p∈P   f (p)   é mínimo
entre todos os caminhos conectando         n a n.

1.1 Considerações iniciais
    •   Ambiente de desenvolvimento do código fonte: Microsoft Visual Studio C 10.0,
        NetBeans 6.9.1.


    •   Compilador: gcc 4.4.5.


    •   Linguagem utilizada: Linguagem C.


    •   Ambiente de desenvolvimento da documentação: TeXnicCenter 1 BETA 7.50-
                    A
        Editor de L T X, Editor dos grafos: R-2.12.0 for windows.
                     E



1.2 Especicações da máquina
    •   Intel Pentium IV 3.0 GHz, 64 bits


    •   Memória: 2 GB


    •   Ubuntu 10.10 AMD 64, kernel 2.6.35-22 generic



1.3 Especicação do problema
1.3.1 Material a ser entregue
    Código em C, incluindo instruções para compilação.          Essas instruções podem,
por exemplo, indicar opções que devem ser usadas na compilação do código em C.
(ex.: -O2 -ast-math). Devem ser oferecidas as seguintes implementações:


    •   Algoritmo de Dijkstra para para computação de c.m. de uma fonte para todos
        os outros vértices;
        →   a fonte deve ser sorteada com a função rand a cada execução do algoritmo
        de Dijkstra dentro do programa.




                                              1
•   Algoritmo Floyd-Warshall (FW) para computação dos caminhos mínimos de
       todos os vértices para todos os outros do grafo;
       → a implementação de FW deve incluir um teste para a existência de ciclos de
       custo negativo no grafo. Caso um seja encontrado, o algoritmo deve concluir
       imediatamente sua execução e indicar o ciclo encontrado.


1.3.2 Documentação impressa incluindo
   •   explicação da implementação, incluindo referências bibliográcas;

   •   tabelas contendo os resultados dos experimentos realizados


1.3.3 Regras de Implementação
   Os códigos devem ser escritos em C, sem o uso de bibliotecas adicionais, exceto
a biblioteca padrão da linguagem ou da biblioteca GNU.
   Os seguintes padrões* C são aceitos:

   •   ANSI C 89

   •   ANSI C 99

   •   GNU C

   *O compilador GCC permite a compilação com validação de códigos com a ag
-std. Ex.: (-std=c99).
   Códigos com vazamento de memória ou problemas do tipo serão penalizados com
-1 pontos. Os códigos serão testados com a ferramenta valgrind.


1.3.4 Problemas Teste

               Instância Vértices Arestas                    Testar
               rome99c.gr       3.353         8.859         Dijkstra
 USA-road-d.NYc.gr.bz2        264.346    730.100            Dijkstra
            rg300_768.gr          300          768    Floyd-Warshall
           rg300_4730.gr          300         4.730   Floyd-Warshall
  comp-2007-2-22c.gr.gz           600    276.666      Floyd-Warshall
                Tabela 1: Instâncias de teste e algoritmos a executar



   •   soluções devem ser checadas; caminhos mínimos pré-computados para rome99:
       spathsRome99c.gr.bz2 (lembre-se que entre dois nós pode haver mais de um
       caminho ótimo possível). outros: nspathsRg300_768.txt.bz2 .

   •   alguns problemas vieram da competição do DIMACS.

   •   os problemas teste para o algoritmo Floyd-Warshall (FW) podem incluir val-
       ores negativos nos custos dos arcos. A implementação de FW, quando encon-
       trar um ciclo de custo negativo, deve abortar a computação e como saída deve
       somente indicar o caminho que indica o ciclo de custo negativo encontrado.

   *


                                          2
1.3.5 Formato de Entrada e Saída e Parâmetros
   O programa deve receber os seguintes argumentos, quando chamado pela linha
de comando:
   prog arquivoProblema nrExecuções flagDepuração
   Onde flagDepuração pode receber valor 0 ou 1. Como exemplo:
   prog rome99.gr 1000 1
   Indica que o programa irá ler o grafo do arquivo rome99.gr, executando o algo-
ritmo de caminhos mínimos 1000 vezes e ao nal irá imprimir/salvar informação de
depuração.
   A informação de depuração que deve ser gerada, quando solicitada, é a seguinte:
   arquivo spaths.txt
   O arquivo spaths.txt deve conter todos os caminhos mínimos computados para
cada par de vértices (s,t), sendo s diferente de t . Cada linha contém a informação
sobre o caminho mínimo de um par (s,t), no formato:
   [s,t](dist) n1 n2 n3 ... nn
   Onde:


   •   s: nó fonte


   •   t: nó destino


   •   dist: distância calculada entre s e t


   •   n1 n2 n3 ...      nn:    caminho computado entre s e t, incluindo todos os nós
       intermediários no formato: s n2 n3 ... t



1.4 Dijkstra
   O algoritmo de dijkstra para caminhos mínimos foi feito por Edsger W. Dijkstra
em 1956 e foi publicado em 1959.            Este algoritmo é um algoritmo de busca em
grafos que resolve o problema de caminhos mínimos para grafos sem ciclos de custo
negativo [5].
   O algoritmo de dijkstra é um algoritmo guloso, pois toma uma decisão que
parece ser a melhor no momento.             Dado um nó fonte ele calcula o caminho de
menor distancia deste nó a todos os outros. Ele funciona semelhante ao BFS, porém
trata grafos com peso.         Ele trata os nós mais próximos da fonte primeiro, porém
essa proximidade se refere ao peso entre as arestas e não ao número de arestas
percorridas. Sua complexidade é         O((|E| + |V |)log|V |)[5].
   Para a execução do algoritmo são utilizados dois vetores auxiliares (dist e
pred) com tamanho igual ao numero de vértices do grafo. O vetor dist armazenará
as distancias do nó fonte até qualquer nó do grafo. O vetor pred armazenará os
anteriores de cada nó no caminho da fonte até ele.            Além disso é necessária uma
heap para saber a ordem de processamento dos nós.
   Ao inicio da execução do algoritmo o vetor de distancias é inicializado com innito
para todos os vértices, exceto o nó fonte s que terá distancia 0. O vetor pred será
todo inicializado com nulo. O algoritmo processa todos os nós da heap. Enquanto
ainda há nós na heap retira-se o menor vértice (u) e, para cada vizinho         v   vértice
verica se a distancia até     v passando por u é menor que a distancia até v já calculada.
Caso seja menor      u   é   marcado como antecessor de v no vetor pred e a distancia



                                                3
até   v   é alterada para a distancia até   u   mais a distancia entre   u   e   v,   atualizando a
heap com a nova distancia.
      As operações que são mais custosas para o algoritmo do dijkstra são as operações
sobre a heap, portanto uma escolha errada de heap pode causar ineciência do
algoritmo.


1.4.1 Heaps
      Heaps são las de prioridade implementadas baseadas em árvores. Existem ba-
sicamente dois tipos de heap, a heap de máximo, em que para cada nó   x na arvore,
x tem chave maior que de todos seus lhos[2], e a heap de mínimo que é utilizada no
algoritmo de dijkstra, em que cada nó x pai sempre é menor que todos seus lhos.
      As heaps para o dijkstra possuem como chave os valores de distancia do vértice
fonte até os respectivos nós. A medida que a distancia encontrada diminui para cada
nó, sua prioridade aumenta e sua vez de ser processado se aproxima, congurando
uma heap de mínimo.
      As funções básicas de uma heap qualquer são:


      •   Inserção


      •   deleção de menor


      •   decremento da chave


      Heaps de Fibonacci:
      Para a versão nal foi feita uma tentativa de implementação da heap de bonacci[7].
As heaps de bonacci são coleções de árvores ordenadas como heaps mínimos[6]. As
heaps de bonacci são implementadas usando listas circulares duplamente encadeadas[1].
A heap é composta da lista de raízes e para cada nó da lista de raízes tem uma lista
de lhos que também pode ter seus lhos, assim em diante. A heap também tem
um ponteiro para o menor nó da lista.
      A inserção na heap de bonacci apenas insere o novo nó na lista de raízes. A
inserção verica se o novo nó é menor que o menor atual, caso seja o menor passa a
ser o novo. Esse procedimento é executado com custo real          O(1).
      Na função de extração do menor nó, o nó apontado por min é removido da
lista de raízes e todos seus lhos são inseridos na lista de raízes. Depois a heap é
consolidada, o que signica que todas as raízes terão grau (numero de lhos na lista)
diferente. Caso haja mais de um nó com um certo grau, o maior deles vira lho do
outro. A menor das raízes passa a ser o novo min. O custo amortizado da função
de extração de menor é       O(logn).
      A diminuição da chave pode fazer com que um lho que menor que seu pai,
ferindo a propriedade das heaps. Caso isso ocorra este nó é cortado do pai e levado
à lista de raízes. Caso o pai seja lho de outro nó e já tenha perdido um lho sendo
lho desde que virou lho de seu nó pai, ele também será cortado de seu pai e virará
raiz da heap, senão apenas será marcado para ser cortado se perder mais lhos. Se
o nó decrementado for menor que a raiz, este passará a ser o novo minimo. O custo
amortizado desta função é       O(1).
      As heaps de bonacci possuem uma estrutura muito complexa, contendo listas
circulares duplamente encadeadas.       Isso dicultou bastante a implementação não
permitindo que fosse encerrada a versão do dijkstra usando essas heaps em tempo



                                                 4
hábil, pois para cada nó há apontador para seu pai, seu irmão da esquerda, seu
     irmão da direita e todos seus lhos. Acredita-se que essas heaps poderiam melhorar
     ainda mais o algoritmo do dijkstra devido à sua boa complexidade. Com as heaps
                                                                          2
     binarias a ordem de complexidade do dijkstra se aproxima muito de O(n logn), com
                                                           2
     heaps de bonacci essa complexidade aproximaria O(n ).


     1.4.2 Aplicação do Algoritmo
     1.4.3 Versão Preliminar x Final
        Para o problema proposto a cada nó da heap é representado pelo índice de seu
     vértice no grafo, índice esse que é usado para a identicação da distancia do nó no
     vetor dist, valor este que é a chave do nó. A função diminui recebe o índice do nó
     que foi alterado, porém não é conhecido seu posicionamento na heap. Para saber
     qual nó da heap foi alterado de inicio foi feita uma busca linear                                           O(n)   em todo o
     vetor da heap, versão que foi enviada na preliminar da competição.
        Para a versão nal essa busca linear foi substituída pela busca em hash que é
     O(1).    Como os possíveis valores da heap são conhecidos (1 até                                        n)      e também seu
     tamanho máximo (n), foi possível fazer um hash mínimo perfeito. Para isso foi criado
     um novo vetor pos, que para cada posição                                i   deste vetor, seu valor corresponde à
     posição do vértice              i   do grafo no vetor da heap.



     1.5 Floyd-Warshall
        O algoritmo de Floyd-Warshall tem como objetivo calcular a menor distância de
     todos os vértices do grafo para todos os demais, recebendo, para isso, uma matriz
     de adjacências representando o grafo.
        Com ordem de complexidade cúbica assume que para percorrer o caminho                A→C
     haverá um caminho            A → B e B → C , isto é, para qualquer par de vértices (i, j) ∈ V ,
     considera-se        todos os caminhos de iaj cujos vértices intermediários pertencem ao
     subconjunto         1, 2, 3..., k , e p como o mais curto de todos eles.
        Em resumo:
        dist(i; j; k):           o comprimento do caminho mais curto entre                               i   e   j   tal que apenas
     os nós   1, ..., k   podem ser usados como intermediários.
        No Programa 1 temos o algoritmo implementado em C.

     void                                ∗                       ∗∗
            int
             f l o y d ( TGrafo              g ,    TVertice          auxMatriz ) {



            int ∗∗
                 k,      i ,   j ;

                      pred ;

       pred    = NULL ;

 5                                                    −q t d V e r t ) ) ;
       for
       pred    =     i n i c i a P r e d ( pred ,( g

                             −q t d V e r t ; i ++)
         for
             ( i =0; i  g

                ( j = 0 ; j g−  q t d V e r t ; j ++)

              a u x M a t r i z [ i ] [ j ] = g−

         for
                                                    m a t r i z [ i ] [ j ] ;

                  ( k = 0 ; k  g−

                   for
                                            q t d V e r t ; k++)

10                                        i  g−

                          for
                          ( i = 0;                  q t d V e r t ;   i ++)

                                                j  g−

                                     if
                                  ( j = 0;                q t d V e r t ;     j ++)

                                             ( ( auxMatriz [ i ] [ k ] . peso        +     auxMatriz [ k ] [ j ] . peso )     

                                             auxMatriz [ i ] [ j ] . peso ) {

                                              auxMatriz [ i ] [ j ] . peso         =     auxMatriz [ i ] [ k ] . peso     +

                                                     auxMatriz [ k ] [ j ] . peso ;



                                               if
                                              pred [ i ] [ j ]   =    pred [ k ] [ j ] ;

15                                                   ( auxMatriz [ i ] [ i ] . peso           0)   {




                                                                         5
return   ;

                                          }

                                    }

         f r e e ( pred [ 0 ] ) ;

20       f r e e ( pred ) ;

     }


                                        Programa 1: Algoritmo Floyd Warshall C



     1.5.1 Aplicação do Algoritmo
          O algoritmo de Floyd-Warshall pode ser utilizado para os seguintes problemas:


          •   Caminhos mais curtos em grafos orientados (algoritmo de Floyd);


          •   Proximidade transitiva de grafos orientados (algoritmo de Warshall);


          •   Encontrar uma expressão regular denotando a linguagem regular aceita por
              um autômato nito (algoritmo de Kleene);


          •   Inversões de matrizes de números reais (algoritmo de Gauss-Jordan);


          •   Roteamento otimizado.              Nesta aplicação, o objetivo é encontrar o caminho
              com o máximo uxo entre dois vértices. Isto signica que, em vez de calcular
              o mínimo, calcula-se o máximo;


          •   Testar se um grafo não-orientado é bipartido.


     1.5.2 Versão Preliminar x Final
        Reinicialização das Matrizes:
          •   Preliminar: Na versão preliminar havia um erro no algoritmo de modo que as
              matrizes de distâncias e dos predecessores não eram reinicializadas quando o
              usuário passava como argumento um número inteiro superior a uma execução.
              Através disso as matrizes não eram reinicializadas a partir da 1 execução.

              Esse problema afetava a execução do programa somente quando não havia
              impressão ou quando o número de execuções fosse superior a 1 (um).


          •   Final: Para melhorar o desempenho bem como corrigir o problema anterior
              alocamos tanto a matriz de distâncias quanto a dos predecessores antes de
              chamar a função do algoritmo Floyd-Warshall e desalocando no nal da ex-
              ecução de todo o programa, assim possibilitou em um ganho de desempenho
              quando levarmos em consideração a alocação das matrizes.

              Um ponto importante a ser citado é que mesmo não alocando e desalocando a
              todo execução sempre reinicializamos as duas matrizes. Isso pode ser percebido
              no Programa 17


          Tratamento do Ciclo Negativo:
          •   Preliminar:           Não havia uma otimização no tratamento de ciclos negativos,
              assim, em cada execução o algoritmo vericava se havia ou não ciclos negativos
              no grafo.


                                                           6
•   Final: Para otimizar o tratamento de ciclos negativos foi incluída na estrutura
              15 do grafo uma variável               ehcicloNeg              que verica na entrada de arquivos, vide
              Programa 16, se no grafo continha ou não peso negativo. Através dessa veri-
              cação, para otimizar, criamos diferentes funções para o algoritmo de Floyd-
              Warshall, sendo para grafos com ciclos negativos: oydPNeg, oydNeg, vide
              Programas 22, 23 respectivamente .

              E para positivos: oydP, oyd, vide Programas 20, 21 respectivamente. Nessas
              funções não realizamos a vericação para caso haja ciclo negativo uma vez que
              o grafo não contém determinado ciclo[3].


          Obs.:      Na Seção 2.4 explicaremos melhor esse método.




     2        Algoritmo e estruturas de dados
     2.1 Grafo do Dijkstra
          O grafo para o algoritmo de dijkstra foi representado pela lista de adjacências
     apresentada na estrutura 2

     #include  s t d a f x . h
     typedef struct
         int
                               {

                    qtdusada , ∗       resultado ;

 5   }   Caminho ;



     typedef struct
         int ∗
                               {

                     vizinhos ,       ∗ pesos    ,       qtdAlloc ,           qtdFree ;

     }   TVertice ;

10
     typedef struct
         int
                               {

                    qtdVert ,      qtdMedia ;

              TVertice    ∗   v;

     }   TGrafo ;

15
     TGrafo       cria_grafo_por_nome (                  char ∗   ) ;



     void      i m p r i m i r _ s a l v a r ( Caminho    ∗) ;

20   void      construindoLista (         int ∗ int ∗,            ,     TGrafo        ∗) ;

     void      addInteracao (        int ∗ int ∗
                                            ,             ,   TGrafo         ∗,   int ∗      ) ;


                                                Programa 2: TAD Grafo




     2.1.1 Função CriaGrafoPorNome
          A Função CriaGrafoPorNome tem como objetivo fazer a leitura do grafo a
     partir de um arquivo .txt e iniciar a lista de adjacências bem como instanciar a lista
     com todos arcos do grafo de um vértice                             A    para um vértice       B.
          Vide Programa 3

     TGrafo       cria_grafo_por_nome (                  char ∗       nome )      {




                                                                         7
∗ arqE ;
            char
            FILE

                       ∗ buf , ∗ tok ;
 5
            int
            TGrafo           g;



                             char ∗                                  sizeof char
                   numArestas ,                       numVertices ,                  vA ,    vB ,    peso ,     media_qtd_arestas ;

            buf   =      (               )       malloc (                        (           )    ∗ BUFSIZ ) ;
            arqE    =        f o p e n ( nome ,                r) ;

10          if    ( ! arqE )         {

                   printf (      Erro ao a b r i r o a r q u i v o de e n t r a d a %s  ,                                      nome ) ;

                   g . q t d V e r t = − 1;

                return               (g) ;



            while
            }

15                       ( ! f e o f ( arqE ) )                  {



                if
                   buf        =   f g e t s ( buf ,                  BUFSIZ ,        arqE ) ;



                    break
                             ( buf    == NULL)

                                             ;



20              switch
                    case ' p '
                                     ( buf [ 0 ] )               {

                                                      :

                                         tok          =                          ) ;
                                                              s t r t o k ( buf ,

                                         tok          =       s t r t o k (NULL,  ) ;
                                         tok          =       s t r t o k (NULL,   ) ;

25                                       numVertices                    =    a t o i ( tok ) ;

                                         tok          =       s t r t o k (NULL,         ) ;
                                         numArestas                    =    a t o i ( tok ) ;

                                         media_qtd_arestas                            =     numArestas          /   numVertices          +    1;



                                         break
                                         c o n s t r u i n d o L i s t a ( n u m V e r t i c e s ,            m e d i a _ q t d _ a r e s t a s ,   g ) ;

30
                              case
                                                          ;

                                             'a ' :
                                         tok          =       s t r t o k ( buf ,      ) ;
                                         tok          =       s t r t o k (NULL,        ) ;
                                         vA =             a t o i ( tok ) ;

35                                       tok          =       s t r t o k (NULL,         ) ;
                                         vB =             a t o i ( tok ) ;

                                         tok          =       s t r t o k (NULL,         ) ;
                                         peso             =    a t o i ( tok ) ;



                                  break
                                         a d d I n t e r a c a o (vA ,               vB ,       g ,   p e s o ) ;

40
                              default
                                                          ;



                                  break
                                                  :

                                                          ;

                   }

            }

45          f c l o s e ( arqE ) ;



            return
            f r e e ( buf ) ;

                             (g) ;

     }


                             Programa 3: Função CriaGrafoPorNome para o dijkstra



     2.1.2 Função ConstruindoLista
         A Função ConstruindoLista tem como objetivo inicializar a lista de adjacências
     para todos os nós. Vide Programa 4

     void                                                     int ∗                  int ∗                              ∗
            int
                construindoLista (                                     qtdV ,                    m ed ia ,   TGrafo         g)   {

                   i ;

            g−q t d M e d i a = ∗ m e d i a ;
            g−q t d V e r t = ∗ qtdV ;


                                                                                        8
5           −v                                    ∗ ) c a l l o c ( ∗ qtdV ,               sizeof
            for
            g         =      ( TVertice                                                               ( TVertice ) ) ;

                    ( i      =   0;     i          ∗ qtdV ; i ++) {
                    g−v [       i ] . qtdAlloc                 =     0;

                     −v [                        ∗ media ;
                                                                          int                               sizeof int
                    g            i ] . qtdFree              =

                    g−                                   ∗ ) c a l l o c ( ∗ me d ia ,
                                                                int                                      sizeof int
                      v [       i ].   vizinhos = (                                                                        (          )) ;

10                  g−v [       i ].   pesos = (    ∗ ) c a l l o c ( ∗ m ed ia ,                                  (           )) ;

            }

     }


                                              Programa 4: Função ConstruindoLista




     2.1.3 Função AddInteração
          A função AddInteração adiciona a interação lida do arquivo ao nó de origem
     da mesma. Vide Programa 5

     void                             ∗ vA , int                     int
                                                        ∗ vB , T G r a f o ∗ g ,        ∗ peso ) {         int
            if
                addInteracao (

                   (!g−v [ ( ∗ vA ) − 1 ] . q t d F r e e ) {
                    g−v [ ( ∗ vA ) − 1 ] . q t d F r e e + = g−

                                                                                      int
                                                                  q t d M e d i a ;

                    g−v [ ( ∗ vA ) − 1 ] . p e s o s = (        ∗ ) r e a l l o c ( g−v [ ( ∗ vA ) − 1 ] . p e s o s ,
                             sizeof int
                                    (   ) ∗ ( g−    v [ ( ∗ vA ) − 1 ] . q t d F r e e + g−    v [ ( ∗ vA ) − 1 ] .



                                                                                            int
                             qtdAlloc ) ) ;

 5                    −v [ ( ∗ vA ) −                                                        ∗ ) r e a l l o c ( g−v [ ( ∗ vA ) − 1 ] .
                                                        sizeof int
                    g                                   1 ] . vizinhos            =     (

                             vizinhos ,                                   (       )    ∗ ( g−v [ ( ∗ vA ) − 1 ] . q t d F r e e + g−v [ ( ∗
                             vA )     −     1 ] . qtdAlloc ) ) ;

            }

            g−v [ ( ∗ vA ) −               1 ] . vizinhos [ g     −v [ ( ∗ vA ) −                1 ] . qtdAlloc ]     =    ( ( ∗ vB ) −     1) ;

            g−v [ ( ∗ vA ) −               1 ] . pesos [ g     −v [ ( ∗ vA ) − 1 ] .             q t d A l l o c ++] =   ∗ peso ;
            g−v [ ( ∗ vA ) −               1 ] . q t d F r e e −−;

10   }


                                              Programa 5: Função ConstruindoLista




     2.2 Heap Binária
          A heap binaria é representada por uma árvore binária completa ou quase com-
     pleta. Para o caso do dijkstra, como a heap é mínima, o pai sempre é menor que
     seus lhos. Para representar a heap há duas estruturas possíveis, lista encadeada
     com ponteiros para os dois lhos e lista simples utilizando um vetor[8]. Na imple-
     mentação foi utilizada a segunda estrutura por ser mais simples de trabalhar. Vide
     Programa 6:

     #include TGrafoD . h
     typedef struct
         int ∗ ∗
                                      Heap          {

                        v,∗      dist ,             pos ,       qtdV ;

 5   }   THeap ;



     int    tamanho ( THeap                 ∗) ;

     void       c r i a H e a p ( THeap      int ∗
                                                ∗,                  ) ;

10
     void       reconstroi (            int int ,           ,    THeap          ∗) ;

     void       c o n s t r o i ( THeap         ∗) ;



                                                                                        9
15   int    p e g a r M e n o r ( THeap          ∗) ;

     void       d i m i n u i ( THeap    ∗,       int ∗      ) ;



     Caminho         d i j k s t r a P ( TGrafo          ∗,        int ∗   ) ;

20
     void       d i j k s t r a ( TGrafo         ∗,     int ∗      ) ;


                                                             Programa 6: TAD Grafo

         Para representar uma árvore com vetor considera-se que para o vértice                                                       i   seus
     lhos são       (2 ∗ i + 1) e (2 ∗ i + 2), sendo sua raiz o nó                                           de índice 0. O pai de um nó
     de índice       i é representado pelo nó de índice ceil(i/2).

     2.2.1 Inicialização da heap
         A função Criaheap 7 aloca todas os vetores da heap e inicializa seus valores
     para os esperados ao inicio do dijkstra.

     void                                    ∗           int ∗
            int
                c r i a H e a p ( THeap           h,                     qtdD )    {

                     i ;

             −             ∗ qtdD ;
                               int                                           sizeof int
            h qtdV =

             −               ∗ ) c a l l o c ( ∗ qtdD ,
                                   int                                          sizeof int
            h v =    (                                                                   (            )) ;

 5          h− d i s t = (        ∗ ) c a l l o c ( ∗ qtdD ,
                                 int                                           sizeof int
                                                                                                  (          )) ;

            h−                  ∗ ) c a l l o c ( ∗ qtdD ,
            for
              p o s = (                                                                       (            )) ;

                 ( i = 0;      i  ∗ qtdD ;       i ++) {

                h− d i s t [ i ] = INF ;
                    

                h−  v [ i ] = i ;

10              h−  p o s [ i ] = i ;

            }



     }


                                                        Programa 7: Criação da heap

         A Inserção para a heap binária consiste em colocar sua chave no vetor e refazer
     o posicionamento do nós no vetor seguindo os índices de forma a respeitar a pro-
     priedade da heap de que o pai é menor que todos os lhos. A ordem de complexidade
     da inserção é           O(logn)[8].              Para o caso do dijkstra todos os nós são inseridos na heap
     logo no começo, para isso existe a função constrói que considera que as                                                  n/2   últimas
     posições do vetor já estão na heap, já que nenhuma posição representa o pai de outra
     já que   i é pai de 2∗i+1 e 2∗i+2 e i é pai de n+1 e n+2, para i = n/2. Considerando
     isso   os n/2 primeiros nós são inseridos na heap pela função reconstrói que verica
     a propriedade da heap, trocando o pai com seu menor lho, caso o lho seja menor
     que o pai. Na teoria são feitas                          n/2 inserções na heap,                          o que gera uma complexidade
     O(nlogn)[2].           Vide Programa 8

     void                                    ∗
            int
                c o n s t r o i ( THeap           h)     {

                     esq ;

                           −
            while
            esq     = h qtdV            /       2;

                           ( e s q =    0)       {

 5                   r e c o n s t r o i ( esq ,          −
                                                         h qtdV            −     1,   h) ;

                    esq     −−;
            }

     }



10   void       reconstroi (       int           esq ,       int         dir ,    THeap       ∗h )      {




                                                                                  10
int
            int
                      i     =       esq ;



            int
                      j ;

                      aux ;

            j    =    i     ∗ 2           +    1;

15                           −
            while
            aux       = h v [ i ] ;



                if
                              ( j   =         dir )             {



                                    if
                                ( j           dir )

                                                −
                                              ( h  d i s t [ h v [ j ] ]−                           −                −
                                                                                                    h  d i s t [ h v [ j       +    1]])



                      if
                                               j ++;

20                                      −                                             −                  −
                                    break
                                ( h  d i s t [ aux ]                     = h  d i s t [ h v [ j ] ] )

                                                   ;

                          −
                      h p o s [ h v [ j ] ]  −                          =    i ;

                          −
                      h v [ i ]                        −
                                               = h v [ j ] ;

                      i     =       j ;

25                    j     =       i     ∗    2       +     1;

            }

                −
            h p o s [ aux ]                   =       i ;

                −
            h v [ i ]              =     aux ;

     }


                                                              Programa 8: Inicialização da heap




     2.2.2 Remove menor
           A remoção do menor é feita pegando sua chave e o trocando com o ultimo
     elemento válido do vetor, que será a folha extrema direita da árvore. Após isso a
     heap é refeita com a função reconstrói desconsiderando a posição onde estava o
     ultimo. Sua complexidade é                                           O(logn)[8].Vide                    Programa 8

     int                                                     ∗
            int
            p e g a r M e n o r ( THeap                              h)   {

                      min ;

                         −
            min = h v [ 0 ] ;

             −
            h v [ 0 ]     = h−    v [( −− h−qtdV )                                      ];

 5          h− p o s [ h−   v [ 0 ] ] = 0 ;

            r e c o n s t r o i ( 0 , h− qtdV − 1 ,

            return
                                                                                            h) ;

                               min ;

     }


                                                                      Programa 9: Remove Menor




     2.2.3 Diminui
           Para decrementar a chave, já que o dijkstra já altera o valor do vetor dist, a
     função apenas verica se o elemento com chave alterada fere a propriedade da heap
     e o troca com seu pai em caso armativo. Isso é feito até que a propriedade volte a
     ser obedecida pelo nó alterado. Vide Program 10

     void                                               ∗h ,          int ∗
            int
                d i m i n u i ( THeap                                                i )    {

                      aux ,             pos ;



            pos                −
                      = h p o s [                 ∗   i ];

 5
            while             ( ( p o s ) =                 1               −
                                                                 h  d i s t [ h v [ (           −          int   )   c e i l ( ( pos )   /   2.)   −   1]]      h

                     − d i s t            −
                                                             int
                                        [ h v [ ( p o s ) ] ] )                     {

                      aux           =     h−v [ (                    )       c e i l ( ( pos )        /     2.)   −    1];




                                                                                                    11
−              int                                                           −             −
                                                             int                                                                     int
                    h v [ (                    )       c e i l ( ( pos )       /       2.)           1]    = h v [ ( p o s ) ] ;

10                   −
                    h p o s [ h v [ (  −                          )     c e i l ( ( pos )       /    2.)     − 1]]       =     (         )   c e i l ( ( pos )   /

                          2.)           − 1;
                     −
                    h v [ ( p o s ) ]                  =     aux ;

                     −
                                        int
                    h p o s [ aux ]= p o s ;

                    pos       =     (               )    c e i l ( ( pos )          /    2.)      −    1;

            }

15   }


                                                             Programa 10: Decrementa Chave




     2.2.4 Tamanho
           Esta função apenas retorna o tamanho da heap. Usada para vericar a existencia
     de elementos na heap. Vide Programa 11

     int                                        ∗
            return
            tamanho ( THeap                             h)    {

                              −
                          h qtdV ;

     }


                                                                        Programa 11: Tamanho




     2.3 Dijkstra
     2.3.1 Função Dijkstra
           Essa função é responsável pela simples execução do algoritmo de Dijkstra sem
     impressão de caminho.

     void       d i j k s t r a ( TGrafo                 ∗    g ,       int ∗   s)       {



            int
            THeap        h;

                    v,    u,        i ,         ∗ prev ;

 5          prev     =    (   int ∗         )       calloc (g    −q t d V e r t              ,       sizeof int (        )) ;

            c r i a H e a p (h ,               (g     −q t d V e r t ) ) ;
            h. dist [     ∗s]           =       0;

            c o n s t r o i (h ) ;



10          while        ( tamanho (h ) )                          {



                for
                    v =       p e g a r M e n o r (h ) ;

                              ( i       =       0;       i         g   −v [ v ] .     qtdAlloc ;            i ++)   {

                                                −v [ v ] .
                              if
                              u = g                                 vizinhos [ i ] ;

                                        (h . dist [ u ]                     h. dist [v]              + g   −v [ v ] .   pesos [ i ] )         {

15                                        h. dist [u]                    = h. dist [v]                + g   −v [ v ] .   pesos [ i ] ;

                                            prev [ u ]              = v;

                                            d i m i n u i (h ,              u ) ;

                              }

                    }

20          }

            free (h . dist ) ;

            free (h . v) ;

            f r e e ( prev ) ;

     }


                                                        Programa 12: Fijkstra sem Impressão




                                                                                             12
2.3.2 Função DijkstraP
        Essa função é responsável pela execução do algoritmo de Dijkstra imprimindo de
     caminho. O caminho que é calculado para cada vertice                                                             v   percorrendo o vetor pred
     iniciando pelo pred[v] seguindo pelo pred até que ele seja igual ao nó fonte do
     dijkstra. Vide Programa 13

     Caminho    d i j k s t r a P ( TGrafo                         ∗   g ,       int ∗       s)   {

         THeap       h;

         Caminho          c ;

                ∗
         int
         FILE        arq ;

 5              v,    w,        u,          aux ,           ∗ prev         ,     i ;



         prev    =    (   int ∗         )     calloc (g    −q t d V e r t                    ,   sizeof int      (       )) ;

         c r i a H e a p (h ,              (g   −q t d V e r t ) ) ;
         h. dist [    ∗s]           =       0;

10       c o n s t r o i (h ) ;




         for    (u =          0;     u          g−q t d V e r t ;                     u++)      {

15              prev [ u ]           =        − 1;

         while
         }

                     ( tamanho (h ) )                             {



             for
                v =       p e g a r M e n o r (h ) ;

                          ( i       =       0;        i           g−v [ v ] .         qtdAlloc ;           i ++)    {

20                                          −v [ v ] .
                          if
                          u = g                                    vizinhos [ i ] ;

                                    (h . dist [ u ]                           h. dist [v]        + g      −v [ v ] .    pesos [ i ] )   {

                                     h. dist [u]                       = h. dist [v]              + g      −v [ v ] .    pesos [ i ] ;

                                        prev [ u ]                 = v;

                                        d i m i n u i (h ,                    u ) ;

25                        }

                }

         }

         w = INF ;



30       for    (u =          0;     u            g      −q t d V e r t ;             u++)      {

                free (g    −v [ u ] .                    pesos ) ;

                f r e e ( g−v [ u ] .                    vizinhos ) ;

         }

         arq    =    fopen (          s p a t h s . t x t  , w ) ;
35
          if   ( ! arq )        {

                                     Erro ao e s c r e v e r no a r q u i v o  ) ;
                return
                printf (

                                ;



                                                  int ∗                                     sizeof int
         }

40                                                                                                                ∗ ( g−q t d V e r t +1) ) ;
         for
         c . resultado               =        (                )       malloc           (             (       )

                                                          −q t d V e r t ;
                if
                (u =          0;     u            g                                    u++)      {

                                     ∗s
                          continue
                     (u ==                        ||        h . d i s t [ u]== w)

                                                      ;

                c . qtdusada                      =       2;

45              c . resultado [ 0 ]                            = h. dist [u ] ;

                c . resultado [ 1 ]                            = u;



                while
                aux       =     prev [ u ] ;

                              ( aux          !=           ∗s     aux                 !=   −1) {
                          c . r e s u l t a d o [ c . q t d u s a d a ++] =                               aux ;

50                        aux        =        p r e v [ aux ] ;

                }




                                                                                             13
c . r e s u l t a d o [ c . qtdusada ]  = ∗s ;

                                               [%d,%d ](% d )  , ( ∗ s ) +1 , u +1 , c . r e s u l t a d o
                     for
                     f p r i n t f ( arq ,                                                                     [0]) ;

                           ( i = c . qtdusada          ; i  0 ;       i −−){

55                           f p r i n t f ( a r q ,  %d , c . r e s u l t a d o [ i ] + 1 ) ;

                     }

                     f p r i n t f ( arq ,        n ) ;
           }

           free ( c . resultado ) ;

60         free (h . dist ) ;

           free (h . v) ;

                         −v ) ;
           return
           free (g

                           c ;

     }


                                                Programa 13: Dijkstra com Impressão




     2.3.3 Função Main para o Dijkstra
         Essa função efetua as chamadas para leitura de arquivos e execução do dijkstra.
     Note que foi feito uso de uma técnica denominada                                      Loop Unrolling para aproveitarmos
     melhor o uso do                 Pipeline       do processador[4], ganhando uma leve melhora no tempo
     de execução do programa.

     #include  T D i j k s t r a . h
     int      int
           main (                 char ∗∗
                                 argc ,                    argv )     {



 5       int         flagDepuracao ,                   nrExecucao ,            vertRand ;

           TGrafo          g;



           if
           Caminho           c ;

                    ( argc           3)    {

                                       C o n f i r a o numero de parametros  ) ;
                     return
                     printf (

10                                    ( EXIT_FAILURE ) ;

           }

           srand ( 0 ) ;

           flagDepuracao                    =    a t o i ( argv [ 3 ] ) ;

           nrExecucao                 =    a t o i ( argv [ 2 ] ) ;

15


           if
           g    =    cria_grafo_por_nome ( a r g v [ 1 ] ) ;

                    ( g . qtdVert        = = − 1) {

                                      n ∗∗ Erro ao c r i a r o g r a f o  ) ;
               return
                     printf (

                                      ( EXIT_FAILURE ) ;

20
           switch
           }



               case
                           ( flagDepuracao )                 {



                    switch
                                 0:



                        case
                                                ( nrExecucao          %   4)    {



                                                 while
                                                  0:

25                                                         ( nrExecucao )              {

                                                        vertRand          =    rand ( )     % g . qtdVert ;

                                                        d i j k s t r a (g ,      v e r t R a n d ) ;

                                                        nrExecucao          −−;

30                                                      vertRand          =    rand ( )     % g . qtdVert ;

                                                        d i j k s t r a (g ,      v e r t R a n d ) ;

                                                        nrExecucao          −−;

                                                        vertRand          =    rand ( )     % g . qtdVert ;




                                                                              14
35                                                     d i j k s t r a (g ,   v e r t R a n d ) ;

                                                       nrExecucao       −−;

                                                       vertRand       =   rand ( )      % g . qtdVert ;

                                                       d i j k s t r a (g ,   v e r t R a n d ) ;

40                                                     nrExecucao       −−;

                                          break
                                          }



                                   case
                                                        ;



                                          while
                                              2:

                                                            ( nrExecucao )         {

45                                                     vertRand       =   rand ( )      % g . qtdVert ;

                                                       d i j k s t r a (g ,   v e r t R a n d ) ;

                                                       nrExecucao       −−;

                                                       vertRand       =   rand ( )      % g . qtdVert ;

50                                                     d i j k s t r a (g ,   v e r t R a n d ) ;

                                                       nrExecucao       −−;

                                       break
                                          }

                                                        ;



55                                 default
                                       while
                                                   :

                                                            ( nrExecucao       −−)      {

                                                       vertRand       =   rand ( )      % g . qtdVert ;

                                                       d i j k s t r a (g ,   v e r t R a n d ) ;



                                          break
                                          }

60                                                      ;



                          break
                          }



                 case
                                    ;

                              1:



65                        vertRand         =       0;

                          c   =    d i j k s t r a P (g ,       v e r t R a n d ) ;

          }



          return         ( EXIT_SUCCESS ) ;

70   }


                                   Programa 14: Programa principal do Dijkstra




     2.4 Grafo do Floyd-Warshall
         Para a representação do grafo utilizamos a estrutura TGrafo 15, onde temos
     uma variável  ehcicloNeg para a vericação se o grafo é negativo ou não bem como
     qtdVert, qtdAres para a quantidade de vértices e arestas respectivamente. O grafo,
     na verdade, é representado por uma matriz de adjacências do tipo TVertice** matriz,
     contendo um peso (distância) de um vértice                                    A    para um vértice     B.   Isso pode ser
     visto facilmente no Programa 15.
         Além de calcular a distância e a matriz de predecessores, para a impressão dos
     caminhos de todos os vértices para todos os demais, foi preciso utilizar a estrutura
     Caminho,     onde        qtdTotal, neg, s, t                 representam a quantidade total de vértices do
     grafo, vericação se o grafo é ou não negativo para a geração do caminho de ciclo
     negativo,   s   e   t    os vértices de início e nal do grafo, respectivamente. E, ainda, o
     resultado   contendo a quantidade de vértices que fazem parte do caminho gerado e o
     próprio caminho de um vértice                          A   para um vértice             B.   Isso pode ser visto na Figura
     5


                                                                          15
#include  s t d a f x . h
     typedef struct
         int ∗
                                 {

                     TP ,      qtdNos ;

 5   }   TPasseio ;



     typedef struct              {

                 ∗
         int
            TPasseio             resultado ;

                     qtdTotal ,       neg ,    s ,       t ;

10   }   Caminho ;



     typedef struct
         int
                                 {

                     peso ;

     }   TVertice ;

15
     typedef struct
         int
                                 {



       short int
                     qtdVert ,       qtdAres ;

                            ehcicloNeg ;

            TVertice        ∗∗    matriz ;

20   }   TGrafo ;



     TGrafo      cria_grafo_por_nome (                    char ∗        ) ;



     void     i m p r i m i r _ s a l v a r ( Caminho          ∗) ;
25
     void     i n i c i a _ m a t r i z ( TGrafo     ∗) ;

     void     i n s t _ m a t r i z ( TGrafo   ∗,        int ∗ int ∗ int ∗
                                                                  ,                 ,                ) ;



30   Caminho     ∗    f l o y d P ( TGrafo    ∗) ;

     void     f l o y d ( TGrafo     ∗,   TVertice             ∗∗ ,     int ∗ ∗         ) ;



     TVertice        ∗∗   alocaMatriz ( TVertice                      ∗ ∗ int ∗
                                                                           ,                  ) ;

35
     int ∗∗    iniciaPred (          int ∗∗    ,     int ∗        ) ;



     Caminho     ∗    f l o y d P N e g ( TGrafo     ∗    ) ;



40   void     f l o y d N e g ( TGrafo    ∗    TVertice               ∗∗       ,   int ∗∗           ) ;


                                                   Programa 15: TAD Grafo




     2.4.1 Função CriaGrafoPorNome
          A Função 2.4.1 tem como objetivo fazer a leitura do grafo a partir de um arquivo
     .txt   e ainda iniciar a matriz de adjacências 2.4.3 bem como instanciar a matriz com
     todos os pesos do grafo de um vértice                              A para um vértice B .              E é claro, vericar para
     todos os vértices do grafo, durante a inserção, se o grafo contém aresta com peso
     negativo.
          Vide Programa 16

     TGrafo      cria_grafo_por_nome (                    char ∗           nome )             {

                      ∗ arqE ;
            char
            FILE

                      ∗ buf , ∗ tok ;
            TGrafo        g;




                                                                               16
5         int
                           char ∗                                  sizeof char
                  numArestas ,                      numVertices ,                      vA ,   vB ,      peso ,   media_qtd_arestas ;

                                                                                                      ∗10) ;
                           char ∗                                  sizeof char
           tok   =     (               )       malloc (                            (          )

           buf   =     (               )       malloc (                            (          )       ∗100) ;
                                                             r) ;
           if
           arqE    =       f o p e n ( nome ,

                 ( ! arqE )        {

10                printf (      Erro ao a b r i r o a r q u i v o de e n t r a d a %s  ,                                nome ) ;

                  g . q t d V e r t = − 1;

                  return           (g) ;

           }



           while
         g . ehcicloNeg            =       0;

15                     ( ! f e o f ( arqE ) )                  {



               if
                  buf       =   f g e t s ( buf ,                  BUFSIZ ,            arqE ) ;



                   break
                           ( buf    == NULL)



               switch
                                           ;



                   case ' p '
                                   ( buf [ 0 ] )               {

20                                                  :

                                       tok          =                          ) ;
                                                            s t r t o k ( buf ,

                                       tok          =       s t r t o k (NULL,  ) ;
                                       tok          =       s t r t o k (NULL,   ) ;

                                       numVertices                      =     a t o i ( tok ) ;

25                                     tok          =       s t r t o k (NULL,               ) ;
                                       numArestas                       =    a t o i ( tok ) ;

                                       g . qtdAres                  =   numArestas ;

                                       g . qtdVert                  =       numVertices ;



                                       break
                                       i n i c i a _ m a t r i z ( g ) ;

30
                            case
                                                        ;

                                           'a ' :
                                       tok          =       s t r t o k ( buf ,          ) ;
                                       tok          =       s t r t o k (NULL,            ) ;
                                       vA =             a t o i ( tok )        −       1;

35                                     tok          =       s t r t o k (NULL,               ) ;
                                       vB =             a t o i ( tok )        −       1;

                                       tok          =       s t r t o k (NULL,               ) ;

                  if
                                       peso             =    a t o i ( tok ) ;

                       ( p e s o 0)

40                     g . ehcicloNeg                        =     1;



                                break
                                       g . m a t r i z [ vA ] [ vB ] . p e s o                    =    peso ;



                            default
                                                        ;



                                break
                                                :

                                                        ;

45                }



           return
           }

                           (g) ;

     }


                                               Programa 16: Função criagrafopornome




     2.4.2 Função alocaMatriz
          Para a alocação da matriz, por padrão, seria feita em ordem de complexidade
     quadrática, no entanto, para otimizar o código zemos em ordem de complexidade
     linear. Para isso foi preciso alocar a matriz com a quantidade de linhas da matriz de
     adjacências e mais uma alocação para a posição matriz[0] com tamanho                                                          Linha ∗
     Coluna,     fazendo, em seguida, um redirecionamento dos endereços da matriz.
          Por exemplo, numa matriz 3x2 alocamos a matriz com 3 posições, sendo que para
     a matriz[0] alocaremos 6 posições. Assim, no redirecionamento dos ponteiros como,



                                                                                         17
por exemplo, a posição matriz[1] receberá o endereço da     matriz[0][i ∗ coluna],   ou
seja,   matriz[0][1x2].   Para melhor entendimento, vide Figura 1 e Programa 17.




                          Figura 1: Figura Repres. Alocação Matriz




                                            18
∗∗                                                                         ∗∗                       int ∗
            int
     TVertice                 alocaMatriz ( TVertice                                                        matriz ,                      tam )    {



                                                                                                                            sizeof
                        i ,   j ;

                                                                  ∗∗)                                       ∗ tam ) ∗                                          ∗) ) ;
            if
            matriz            =     ( TVertice                                    malloc ((                                                 ( TVertice

                   ( matriz              == NULL)                         {

 5                                        Erro ao a l o c a r a m a t r i z n ) ;
                        return
                        printf (

                                            0;



                                                                                                                                                       sizeof
            }

            matriz [ 0 ]                =       ( TVertice                    ∗)          malloc ( ( (              ∗ tam ) ∗ ( ∗ tam ) ) ∗                       ( TVertice ) )



            if
                    ;

                   ( matriz [ 0 ]                   == NULL)                          {

10                                        Erro ao a l o c a r a m a t r i z n ) ;
                        return
                        printf (

                                            0;



            for
            }

                        ( i   =     1;          i        (   ∗ tam ) ;                   i ++)         {

                        matriz [ i ]                 = ( m a t r i z [ 0 ] [ i                             ∗   (   ∗ tam ) ] )   ;

15
            return
            }

                              matriz ;

     }


                                                              Programa 17: Função alocaMatriz




     2.4.3 Função iniciaMatriz
         Função responsável por alocar 2.4.2 e inicializar a matriz de adjacências. Vide
     Programa 18

     void                                                                     ∗
            int
                i n i c i a _ m a t r i z ( TGrafo                                    g)       {

                        i ,   j ;

             −                                                          −m a t r i z , (g−q t d V e r t ) ) ;
            for
            g    m a t r i z           =       alocaMatriz (g

                                                           −q t d V e r t ; i ++)
                        for
                        ( i   =     0;          i        g

 5                                ( j    =          0;    j  g−  q t d V e r t ;  j ++)

                                    −m a t r i z [ i ] [ j ] . p e s o = INF ;
            for
                               g

                        ( i   =     0; i  g−      q t d V e r t ;    i ++)

                    g    −m a t r i z [             i ] [ i ] . peso                      =       0;

     }


                                                              Programa 18: Função iniciamatriz




     2.4.4 Função iniciaPred
         Função semelhante a Função iniciaMatriz 2.4.3. Vide Programa 19

     int ∗∗                                         int ∗∗                                 int ∗
          int
                 iniciaPred (                                         pred ,                                tam )       {



          if
                        i ,   j ;



                                                int ∗ ∗                                                                 sizeof int ∗
                   ( pred           == NULL)                      {

                                                                                                   ∗ tam ) ∗
                        if
                        pred        =       (                 )       malloc ((                                                       (           )) ;

 5                            ( pred                == NULL)                      {

                                                          Erro ao a l o c a r a m a t r i z n ) ;
                               return
                                  printf (

                                                         0;



                                                         int ∗                                                                                sizeof int
                        }

                                                                                                            ∗ tam ) ∗ ( ∗ tam ) ) ∗
                        if
                        pred [ 0 ]              =    (                )       malloc ( ( (                                                                 (        )) ;

10                            ( pred [ 0 ]                == NULL)                         {

                                                          Erro ao a l o c a r a m a t r i z  ) ;
                               return
                                  printf (

                                                         0;



                        for
                        }

                                  ( i    =          1;    i              (   ∗ tam ) ;             i ++)           {




                                                                                                             19
15                               pred [ i ]               = ( p r e d [ 0 ] [ (               ∗ tam ) ∗            i ]) ;

                      }



           for
           }

                                                              ∗ tam ) ; i ++)
               for
                      ( i   =      0;        i           (

                                 ( j     =       0;       j     ( ∗ tam ) ;  j ++)

20
           return
                                 pred [ i ] [ j ]                =       i ;

                             pred ;

     }


                                                               Programa 19: Função iniciaPred




     2.5 Floyd-Warshall
     2.5.1 Função oydP
          Função responsável por calcular a distância e predecessores de todos os vértices
     do grafo positivo, utilizando o Algoritmo de Floyd Warshall, note que não é preciso
     reinicializar a matriz de adjacências bem como a de predecessores uma vez que
     quando passarmos ao programa a                                                ag 1        de impressão o programa executará somente
     uma única vez.
          Para uma ilustração da geração dos caminhos veja a Figura 5. Vide Programa
     20

                  ∗                                             ∗
           int
     Caminho              f l o y d P ( TGrafo                          g)     {

                      k,     i ,       j ,       aux ,          n =          0,        pos ;

                             ∗
           int ∗∗
           Caminho                 c ;

                            pred ;

 5         pred        = NULL ;

                                                                                (g−

                                                                                                              sizeof
           pred        =     i n i c i a P r e d ( pred ,                             q t d V e r t ) ) ;

           c    =     ( Caminho              ∗)       malloc (g                −q t d V e r t ∗                                 ( Caminho ) ) ;

           c−n e g         =      0;

           c−s =            0;

10         c−                 −q t d V e r t ;
           for
             t =            g

                                0 ; k  g−

                      for
                      (k =                      q t d V e r t ; k++)

                                            i  g−

                                 for
                              ( i = 0;                q t d V e r t ;    i ++)

                                                   j  g−

                                             if
                                    ( j = 0;                  q t d V e r t ;    j ++)

                                         ( ( g−  m a t r i z [ i ] [ k ] . p e s o + g−m a t r i z [ k ] [                                         j ] . peso )      −
                                                                                                                                                                        g

                                                       matriz [ i ] [ j ] . peso )                          {

15                                                        g   −m a t r i z [           i ] [ j ] . peso            = g    −m a t r i z [   i ] [ k ] . peso   + g −
                                                                    matriz [ k ] [ j ] . peso ;

                                                          pred [ i ] [ j ]               =     pred [ k ] [ j ] ;

                                             }

               −q t d T o t a l = g−q t d V e r t ;
           for
           c

                   ( k = c−     s ; k  c−

                                                                                                                                                     sizeof
                                             t ; k++)                                          {

20                    c [ k ] . resultado                        =       ( TPasseio             ∗)       calloc (c           −q t d T o t a l   ,              (



                      for
                             TPasseio ) ) ;

                                                     −s ;                         −t ;
                                                                                                        int ∗                                                 sizeof
                                 ( i     =       c                  i         c               i ++)      {

                                                                                                                                      −q t d T o t a l
                                         int
                                 c [ k ] . r e s u l t a d o [ i ] . TP =                           (           )    calloc (c                            ,                 (



                                          if
                                                     )) ;



                                                          continue
                                                      ( i      == k)

                                                                                   ;

25                               c [ k ] . r e s u l t a d o [ i ] . TP [ 0 ]                           = g −m a t r i z [ k ] [       i ] . peso ;

                                 c [ k ] . r e s u l t a d o [ i ] . qtdNos                             =     1;

                                 pos         =       1;



                                 while
                                 aux         =       pred [ k ] [ i ] ;

                                                     ( ( aux            !=     i )           ( aux      !=        k) )     {




                                                                                                 20
30                                             c [ k ] . r e s u l t a d o [ i ] . q t d N o s ++;

                                               c [ k ] . r e s u l t a d o [ i ] . TP [ p o s ++] =      aux ;

                                               aux       =    p r e d [ k ] [ aux ] ;

                                 }

                         }

35               }

                 f r e e ( pred [ 0 ] ) ;



                 return
                 f r e e ( pred ) ;

                               c ;

     }


                                                                Programa 20: Função oydP




     2.5.2 Função oyd
             Análogo a Função oydP 2.5.1, porém sem geração de caminhos e ainda dois
     pontos importantes:


             •    Matriz de Distâncias:                            criamos uma matriz auxiliar que é alocada somente
                  uma única vez e desalocada somente no nal das                                            n   execuções, porém sempre
                  que é executada, inicializamos a matriz de modo que que de acordo com a
                  especicação proposta pelo trabalho e ainda com código mais otimizado.


             •    Matriz de Predecessores:                              Optamos por reutilizá-la, porém reiniciando-a na
                  Função mainF 2.5.6 a cada execução. A função responsável por alocar e /
                  ou inicialização do Pred pode ser conferida na Seção 2.4.4. Vale lembrar que
                  a cada execução a matriz de predecessores é reinicializada, logo está de acordo
                  com a especicação proposta pelo trabalho e ainda mais otimizado.



     void                                          ∗                        ∗∗                       int ∗∗
                 int
                     f l o y d ( TGrafo                 g ,   TVertice            auxMatriz ,                   pred )   {



                 for
                         k,    i ,       j ;

                                                 −q t d V e r t ; i ++)
                         for
                         ( i   =     0;        i        g

                                   ( j    =         g−
                                                   0;     jq t d V e r t ; j ++)

 5                              a u x M a t r i z [ i ] [ j ] = g−

                 for
                                                                    m a t r i z [ i ] [ j ] ;

                               = 0 ; k  g−

                         for
                         (k                        q t d V e r t ; k++) {

                                                i  g−

                                   for
                                ( i = 0;                   q t d V e r t ; i ++)

                                                        j  g−

                                               if
                                       ( j = 0;                  q t d V e r t ;  j ++)

                                                        ( ( auxMatriz [ i ] [ k ] . peso        +      auxMatriz [ k ] [ j ] . peso )   

                                                        auxMatriz [ i ] [ j ] . peso )          {

10                                                       auxMatriz [ i ] [ j ] . peso          =     auxMatriz [ i ] [ k ] . peso   +

                                                                auxMatriz [ k ] [ j ] . peso ;

                                                         pred [ i ] [ j ]     =   pred [ k ] [ j ] ;

                                               }

         }

     }


                                                                 Programa 21: Função oyd




     2.5.3 Função oydPNeg
             Função responsável por calcular a distância e predecessores de todos os vértices
     do grafo negativo, utilizando o Algoritmo de Floyd Warshall, note que assim como
     o Programa20 não é preciso reinicializar a matriz de adjacências bem como a de



                                                                                    21
predecessores uma vez que quando passarmos ao programa a                                                                            ag 1    de impressão o
     programa executará somente uma única vez. Logo, bastará somente inicializá-la.
          Como o grafo é negativo (contém ciclos com pesos negativos), então será necessário
     sair da execução do algoritmo de Warshall e identicar o ciclo de peso negativo,
     gerando o caminho desse ciclo para futura impressão em arquivo.                                                                                  Isso é feito de
     modo análogo à geração de caminho da Seção 2.5.1, mas, para isso, bastará percor-
     rer e gerar o caminho da posição da matriz que foi identicado o ciclo negativo, ou
     seja, a posição de uma das diagonais principais da matriz de adjacências do grafo.
          Obs.:          Para contornar a condição de parada do programa para ciclos negativos,
     incrementamos uma unidade na quantidade da posição em que a matriz sua diagonal
     principal foi modicada, isso somente para a representação do vértice nal.
          Para uma ilustração da geração dos caminhos veja a Figura 14. Vide Programa
     22

                    ∗                                                 ∗
             int
     Caminho             f l o y d P N e g ( TGrafo                        g)     {

                        k,    i ,       j ,       aux ,         n =       0,     pos ;

                              ∗
             int ∗∗
             Caminho                  c ;

                             pred ;

 5           pred        = NULL ;

                                                                           (g−

                                                                                                        sizeof
             pred        =    i n i c i a P r e d ( pred ,                       q t d V e r t ) ) ;

             c    =     ( Caminho               ∗)     malloc (g          −q t d V e r t ∗                                ( Caminho ) ) ;

             c−n e g         =       0;

             c−s =           0;

10           c−                −q t d V e r t ;
             for
               t =           g

                                 0 ; k  g−

                        for
                        (k =                     q t d V e r t ; k++) {

                                             i  g−

                                  for
                               ( i = 0;                q t d V e r t ;    i ++)

                                                    j  g−

                                                if
                                     ( j = 0;                  q t d V e r t ;    j ++) {

                                          ( ( g−  m a t r i z [ i ] [ k ] . p e s o + g− m a t r i z [ k ] [                                   j ] . peso )       −
                                                                                                                                                                     g

                                                        matriz [ i ] [ j ] . peso )                   {

15                                                         g−m a t r i z [       i ] [ j ] . peso            = g    −m a t r i z [      i ] [ k ] . peso   + g −
                                                                 matriz [ k ] [ j ] . peso ;



                                                           if
                                                           pred [ i ] [ j ]        =     pred [ k ] [ j ] ;

                                                                 (g   −m a t r i z [ i ] [        i ] . peso              0)     {

                                                                     c−n e g = 1 ;

                                                                     c−s = i ;

20                                                                   c−

                                                                     goto
                                                                       t = i + 1 ;

                                                                                 NEG ;

                                                           }

                                              }

                                  }

25           }

     NEG :

                 −q t d T o t a l = g−q t d V e r t ;
             for
             c

                     ( k = c−     s ; k  c−

                                                                                                                                                 sizeof
                                               t ; k++)                                  {

                        c [ k ] . resultado                     =     ( TPasseio          ∗)       calloc (c          −q t d T o t a l      ,               (



                        for
                              TPasseio ) ) ;

30                                                    −s ;                    −t ;
                                                                                                  int ∗                                                    sizeof
                                  ( i       =     c              i        c             i ++)      {

                                                                                                                                   −q t d T o t a l
                                            int
                                  c [ k ] . r e s u l t a d o [ i ] . TP =                    (           )    calloc (c                               ,                 (

                                                      )) ;

                                  c [ k ] . r e s u l t a d o [ i ] . TP [ 0 ]                    = g −m a t r i z [ k ] [            i ] . peso ;

                                  c [ k ] . r e s u l t a d o [ i ] . qtdNos                      =     1;

                                  pos         =       1;

35
                                  while
                                  aux         =       pred [ k ] [ i ] ;

                                                      ( ( aux        !=    i )         ( aux      !=        k) )     {

                                              c [ k ] . r e s u l t a d o [ i ] . q t d N o s ++;

                                              c [ k ] . r e s u l t a d o [ i ] . TP [ p o s ++] =                         aux ;




                                                                                           22
aux      =     p r e d [ k ] [ aux ] ;

40                            }

                    }

            }

            f r e e ( pred [ 0 ] ) ;



            return
            f r e e ( pred ) ;

45                          c ;

     }


                                                            Programa 22: Função oydPNeg




     2.5.4 Função oydNeg
         Análogo a Função oydPNeg 2.5.3, porém sem geração de caminhos e ainda
     com o mesmo ponto importante da Seção 2.5.2.

     void                                               ∗                           ∗∗                       int ∗∗
            int
                f l o y d N e g ( TGrafo                     g ,    TVertice             auxMatriz ,                   pred )   {



            for
                    k,      i ,       j ;

                                              −q t d V e r t ; i ++)
                     for
                     ( i    =     0;          i        g

                                ( j       =      g−
                                                  0;    j
                                                        q t d V e r t ; j ++)

 5                           a u x M a t r i z [ i ] [ j ] = g−

            for
                                                                 m a t r i z [ i ] [ j ] ;

                            = 0 ; k  g−

                     for
                     (k                         q t d V e r t ; k++)

                                             i  g−

                                for
                             ( i = 0;                   q t d V e r t ; i ++)

                                                     j  g−

                                              if
                                    ( j = 0;                  q t d V e r t ;  j ++)

                                                       ( ( auxMatriz [ i ] [ k ] . peso           +      auxMatriz [ k ] [ j ] . peso )   

                                                       auxMatriz [ i ] [ j ] . peso )             {

10                                                      auxMatriz [ i ] [ j ] . peso             =    auxMatriz [ i ] [ k ] . peso   +

                                                               auxMatriz [ k ] [ j ] . peso ;



                                                        if
                                                        pred [ i ] [ j ]        =   pred [ k ] [ j ] ;



                                                                   return
                                                               ( auxMatriz [ i ] [ i ] . peso                0)   {

                                                                            ;

                                                        }

15                                            }

     }


                                                             Programa 23: Função oydNeg




     2.5.5 Função imprimirsalvar
         Função utilizada para impressão dos resultados, isto é, distância e peso de todos
     os vértices para os demais vértices do grafo bem como o caminho entres os vértices
     de início e nal.
         Obs.:        Como os caminhos de cada vértice são acessados e armazenados em ordem
     inversa a impressão dos caminhos é feita em ordem inversa para que os caminhos de
     saída estejam na ordem correta. Um exemplo dessa geração de caminhos pode ser
     vista na Figura 5. Vide Programa 24

     void       i m p r i m i r _ s a l v a r ( Caminho                ∗    c)      {

                    ∗
            int
            FILE           arqS ;

                     i ,    j ,       k;

                                                   s p a t h s . t x t  , w ) ;
            if
            arqS        =   fopen (

 5                 ( ! arqS )             {

                                           Erro ao e s c r e v e r no a r q u i v o  ) ;
                    return
                     printf (

                                      ;



            if
            }

                   (c   −n e g )


                                                                                        23
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall
Caminhos Mínimos: Dijkstra e Floyd-Warshall

Weitere ähnliche Inhalte

Was ist angesagt? (20)

Introducao redes
Introducao redesIntroducao redes
Introducao redes
 
Manual de portugol
Manual de portugolManual de portugol
Manual de portugol
 
Introdução à sistemas distribuídos
Introdução à sistemas distribuídosIntrodução à sistemas distribuídos
Introdução à sistemas distribuídos
 
Aula 12 - Processador
Aula 12 - ProcessadorAula 12 - Processador
Aula 12 - Processador
 
Big Data e Análise de Dados Massivos
Big Data e Análise de Dados MassivosBig Data e Análise de Dados Massivos
Big Data e Análise de Dados Massivos
 
Trabalho linux
Trabalho linuxTrabalho linux
Trabalho linux
 
DDR5
DDR5DDR5
DDR5
 
Placa mãe
Placa mãePlaca mãe
Placa mãe
 
Python - Introdução
Python - IntroduçãoPython - Introdução
Python - Introdução
 
Arquitetura de computadores Módulo 4
Arquitetura de computadores Módulo 4Arquitetura de computadores Módulo 4
Arquitetura de computadores Módulo 4
 
Aula 10 semana
Aula 10 semanaAula 10 semana
Aula 10 semana
 
Estimativa de software usando pontos de função
Estimativa de software usando pontos de funçãoEstimativa de software usando pontos de função
Estimativa de software usando pontos de função
 
Algoritmos Lista 1 de exercícios gabarito
Algoritmos Lista 1 de exercícios gabaritoAlgoritmos Lista 1 de exercícios gabarito
Algoritmos Lista 1 de exercícios gabarito
 
Aula 3 compiladores e interpretadores
Aula 3   compiladores e interpretadoresAula 3   compiladores e interpretadores
Aula 3 compiladores e interpretadores
 
Comunicação de dados - Módulo 1
Comunicação de dados - Módulo 1Comunicação de dados - Módulo 1
Comunicação de dados - Módulo 1
 
Redes de computadores
Redes de computadoresRedes de computadores
Redes de computadores
 
Camada de enlace parte1
Camada de enlace   parte1Camada de enlace   parte1
Camada de enlace parte1
 
Logica Digital
Logica DigitalLogica Digital
Logica Digital
 
Visualg
VisualgVisualg
Visualg
 
Endereços IP´s
Endereços IP´sEndereços IP´s
Endereços IP´s
 

Andere mochten auch

Algoritmo de Floyd-Warshall
Algoritmo de Floyd-WarshallAlgoritmo de Floyd-Warshall
Algoritmo de Floyd-WarshallJoao Silva
 
Caminho Mínimo em Grafos - Algoritmo de Bellman-Ford
Caminho Mínimo em Grafos - Algoritmo de Bellman-FordCaminho Mínimo em Grafos - Algoritmo de Bellman-Ford
Caminho Mínimo em Grafos - Algoritmo de Bellman-FordGabriel Albuquerque
 
Caminhos Mínimos - Algoritmo de Dijkstra
Caminhos Mínimos - Algoritmo de DijkstraCaminhos Mínimos - Algoritmo de Dijkstra
Caminhos Mínimos - Algoritmo de DijkstraMarcos Castro
 
AI - Backtracking vs Depth-First Search (DFS)
AI - Backtracking vs Depth-First Search (DFS)AI - Backtracking vs Depth-First Search (DFS)
AI - Backtracking vs Depth-First Search (DFS)Johnnatan Messias
 
Cálculo Numérico: Integração Numérica com Bubble Sort
Cálculo Numérico: Integração Numérica com Bubble SortCálculo Numérico: Integração Numérica com Bubble Sort
Cálculo Numérico: Integração Numérica com Bubble SortJohnnatan Messias
 
Análise de Disco, I/O e Processamento
Análise de Disco, I/O e ProcessamentoAnálise de Disco, I/O e Processamento
Análise de Disco, I/O e ProcessamentoJohnnatan Messias
 
Avaliação de Usabilidade, Comunicabilidade e Acessibilidade - Quadro de Avisos
Avaliação de Usabilidade, Comunicabilidade e Acessibilidade - Quadro de AvisosAvaliação de Usabilidade, Comunicabilidade e Acessibilidade - Quadro de Avisos
Avaliação de Usabilidade, Comunicabilidade e Acessibilidade - Quadro de AvisosJohnnatan Messias
 
Algoritmo clique maximo - Analise de Algoritmos
Algoritmo clique maximo  - Analise de AlgoritmosAlgoritmo clique maximo  - Analise de Algoritmos
Algoritmo clique maximo - Analise de AlgoritmosAdilmar Dantas
 
Treinamento Para Competições de Programação - All Pairs Shortest Paths - O Al...
Treinamento Para Competições de Programação - All Pairs Shortest Paths - O Al...Treinamento Para Competições de Programação - All Pairs Shortest Paths - O Al...
Treinamento Para Competições de Programação - All Pairs Shortest Paths - O Al...Murilo Adriano Vasconcelos
 
Análise de Algoritmos - Conceitos de Grafos
Análise de Algoritmos - Conceitos de GrafosAnálise de Algoritmos - Conceitos de Grafos
Análise de Algoritmos - Conceitos de GrafosDelacyr Ferreira
 
Análise de Algoritmos - Programação Dinâmica
Análise de Algoritmos - Programação DinâmicaAnálise de Algoritmos - Programação Dinâmica
Análise de Algoritmos - Programação DinâmicaDelacyr Ferreira
 
Análise de Algoritmos - Método Guloso
Análise de Algoritmos - Método GulosoAnálise de Algoritmos - Método Guloso
Análise de Algoritmos - Método GulosoDelacyr Ferreira
 
Classes de problemas p, np,np completo e np-difícil
Classes de problemas p, np,np completo e np-difícilClasses de problemas p, np,np completo e np-difícil
Classes de problemas p, np,np completo e np-difícilGuilherme Coelho
 
Análise de Algoritmos - Solução de Recorrências
Análise de Algoritmos - Solução de RecorrênciasAnálise de Algoritmos - Solução de Recorrências
Análise de Algoritmos - Solução de RecorrênciasDelacyr Ferreira
 
Análise de Algoritmos - Problemas, instâncias, algoritmos e tempo
Análise de Algoritmos - Problemas, instâncias, algoritmos e tempoAnálise de Algoritmos - Problemas, instâncias, algoritmos e tempo
Análise de Algoritmos - Problemas, instâncias, algoritmos e tempoDelacyr Ferreira
 
Algoritmos Gulosos - Troco Mínimo
Algoritmos Gulosos - Troco MínimoAlgoritmos Gulosos - Troco Mínimo
Algoritmos Gulosos - Troco MínimoGabriel Albuquerque
 
Otimização, dicas de implementação, como resolver problemas by Adriano Santan...
Otimização, dicas de implementação, como resolver problemas by Adriano Santan...Otimização, dicas de implementação, como resolver problemas by Adriano Santan...
Otimização, dicas de implementação, como resolver problemas by Adriano Santan...iPhoneDevBr
 
Análise de Algoritmos - Mais problemas NP-Completos
Análise de Algoritmos - Mais problemas NP-CompletosAnálise de Algoritmos - Mais problemas NP-Completos
Análise de Algoritmos - Mais problemas NP-CompletosDelacyr Ferreira
 
Análise de Algoritmos - As classes P e NP
Análise de Algoritmos - As classes P e NPAnálise de Algoritmos - As classes P e NP
Análise de Algoritmos - As classes P e NPDelacyr Ferreira
 

Andere mochten auch (20)

Algoritmo de Floyd-Warshall
Algoritmo de Floyd-WarshallAlgoritmo de Floyd-Warshall
Algoritmo de Floyd-Warshall
 
Caminho Mínimo em Grafos - Algoritmo de Bellman-Ford
Caminho Mínimo em Grafos - Algoritmo de Bellman-FordCaminho Mínimo em Grafos - Algoritmo de Bellman-Ford
Caminho Mínimo em Grafos - Algoritmo de Bellman-Ford
 
Caminhos Mínimos - Algoritmo de Dijkstra
Caminhos Mínimos - Algoritmo de DijkstraCaminhos Mínimos - Algoritmo de Dijkstra
Caminhos Mínimos - Algoritmo de Dijkstra
 
AI - Backtracking vs Depth-First Search (DFS)
AI - Backtracking vs Depth-First Search (DFS)AI - Backtracking vs Depth-First Search (DFS)
AI - Backtracking vs Depth-First Search (DFS)
 
Cálculo Numérico: Integração Numérica com Bubble Sort
Cálculo Numérico: Integração Numérica com Bubble SortCálculo Numérico: Integração Numérica com Bubble Sort
Cálculo Numérico: Integração Numérica com Bubble Sort
 
Análise de Disco, I/O e Processamento
Análise de Disco, I/O e ProcessamentoAnálise de Disco, I/O e Processamento
Análise de Disco, I/O e Processamento
 
Avaliação de Usabilidade, Comunicabilidade e Acessibilidade - Quadro de Avisos
Avaliação de Usabilidade, Comunicabilidade e Acessibilidade - Quadro de AvisosAvaliação de Usabilidade, Comunicabilidade e Acessibilidade - Quadro de Avisos
Avaliação de Usabilidade, Comunicabilidade e Acessibilidade - Quadro de Avisos
 
Algoritmo clique maximo - Analise de Algoritmos
Algoritmo clique maximo  - Analise de AlgoritmosAlgoritmo clique maximo  - Analise de Algoritmos
Algoritmo clique maximo - Analise de Algoritmos
 
Treinamento Para Competições de Programação - All Pairs Shortest Paths - O Al...
Treinamento Para Competições de Programação - All Pairs Shortest Paths - O Al...Treinamento Para Competições de Programação - All Pairs Shortest Paths - O Al...
Treinamento Para Competições de Programação - All Pairs Shortest Paths - O Al...
 
Análise de Algoritmos - Conceitos de Grafos
Análise de Algoritmos - Conceitos de GrafosAnálise de Algoritmos - Conceitos de Grafos
Análise de Algoritmos - Conceitos de Grafos
 
Análise de Algoritmos - Programação Dinâmica
Análise de Algoritmos - Programação DinâmicaAnálise de Algoritmos - Programação Dinâmica
Análise de Algoritmos - Programação Dinâmica
 
Análise de Algoritmos - Método Guloso
Análise de Algoritmos - Método GulosoAnálise de Algoritmos - Método Guloso
Análise de Algoritmos - Método Guloso
 
Classes de problemas p, np,np completo e np-difícil
Classes de problemas p, np,np completo e np-difícilClasses de problemas p, np,np completo e np-difícil
Classes de problemas p, np,np completo e np-difícil
 
Análise de Algoritmos - Solução de Recorrências
Análise de Algoritmos - Solução de RecorrênciasAnálise de Algoritmos - Solução de Recorrências
Análise de Algoritmos - Solução de Recorrências
 
Análise de Algoritmos - Problemas, instâncias, algoritmos e tempo
Análise de Algoritmos - Problemas, instâncias, algoritmos e tempoAnálise de Algoritmos - Problemas, instâncias, algoritmos e tempo
Análise de Algoritmos - Problemas, instâncias, algoritmos e tempo
 
Algoritmos Gulosos - Troco Mínimo
Algoritmos Gulosos - Troco MínimoAlgoritmos Gulosos - Troco Mínimo
Algoritmos Gulosos - Troco Mínimo
 
Algoritmo Guloso
Algoritmo GulosoAlgoritmo Guloso
Algoritmo Guloso
 
Otimização, dicas de implementação, como resolver problemas by Adriano Santan...
Otimização, dicas de implementação, como resolver problemas by Adriano Santan...Otimização, dicas de implementação, como resolver problemas by Adriano Santan...
Otimização, dicas de implementação, como resolver problemas by Adriano Santan...
 
Análise de Algoritmos - Mais problemas NP-Completos
Análise de Algoritmos - Mais problemas NP-CompletosAnálise de Algoritmos - Mais problemas NP-Completos
Análise de Algoritmos - Mais problemas NP-Completos
 
Análise de Algoritmos - As classes P e NP
Análise de Algoritmos - As classes P e NPAnálise de Algoritmos - As classes P e NP
Análise de Algoritmos - As classes P e NP
 

Ähnlich wie Caminhos Mínimos: Dijkstra e Floyd-Warshall

Linux basico
Linux basicoLinux basico
Linux basicoTiago
 
Algoritmos jabour
Algoritmos jabourAlgoritmos jabour
Algoritmos jabourfjabour
 
Apostila c# iniciantes
Apostila c# iniciantesApostila c# iniciantes
Apostila c# iniciantesCaique Moretto
 
Livro numerico ime usp
Livro numerico ime uspLivro numerico ime usp
Livro numerico ime usplcrslcrs
 
LIVRO_INTRODUÇÃO AO R.pdf
LIVRO_INTRODUÇÃO AO R.pdfLIVRO_INTRODUÇÃO AO R.pdf
LIVRO_INTRODUÇÃO AO R.pdfTAYANEMOURA4
 
Apostila sobre Controle Digital
Apostila sobre Controle DigitalApostila sobre Controle Digital
Apostila sobre Controle DigitalFernando Passold
 
Guia Aberto Android ed.2
Guia Aberto Android ed.2Guia Aberto Android ed.2
Guia Aberto Android ed.2Átila Camurça
 
K19 k21-persistencia-com-jpa2-e-hibernate
K19 k21-persistencia-com-jpa2-e-hibernateK19 k21-persistencia-com-jpa2-e-hibernate
K19 k21-persistencia-com-jpa2-e-hibernateElton Alex Silva
 
Análise de Algoritmos de Ordenação Interna
Análise de Algoritmos de Ordenação InternaAnálise de Algoritmos de Ordenação Interna
Análise de Algoritmos de Ordenação InternaJohnnatan Messias
 
Shell script
Shell scriptShell script
Shell scriptTiago
 
Programming Languages Paradigms
Programming Languages ParadigmsProgramming Languages Paradigms
Programming Languages Paradigmsrodrigovmoraes
 

Ähnlich wie Caminhos Mínimos: Dijkstra e Floyd-Warshall (20)

Apostila geo gebra
Apostila geo gebraApostila geo gebra
Apostila geo gebra
 
Linux basico
Linux basicoLinux basico
Linux basico
 
Tutorial de Uppaal
Tutorial de UppaalTutorial de Uppaal
Tutorial de Uppaal
 
Apostila winplot
Apostila winplotApostila winplot
Apostila winplot
 
Manual do Kile
Manual do KileManual do Kile
Manual do Kile
 
Algoritmos jabour
Algoritmos jabourAlgoritmos jabour
Algoritmos jabour
 
Apostila c# iniciantes
Apostila c# iniciantesApostila c# iniciantes
Apostila c# iniciantes
 
Livro numerico ime usp
Livro numerico ime uspLivro numerico ime usp
Livro numerico ime usp
 
LIVRO_INTRODUÇÃO AO R.pdf
LIVRO_INTRODUÇÃO AO R.pdfLIVRO_INTRODUÇÃO AO R.pdf
LIVRO_INTRODUÇÃO AO R.pdf
 
Apostila sobre Controle Digital
Apostila sobre Controle DigitalApostila sobre Controle Digital
Apostila sobre Controle Digital
 
Php
PhpPhp
Php
 
Guia Aberto Android ed.2
Guia Aberto Android ed.2Guia Aberto Android ed.2
Guia Aberto Android ed.2
 
K19 k21-persistencia-com-jpa2-e-hibernate
K19 k21-persistencia-com-jpa2-e-hibernateK19 k21-persistencia-com-jpa2-e-hibernate
K19 k21-persistencia-com-jpa2-e-hibernate
 
Análise de Algoritmos de Ordenação Interna
Análise de Algoritmos de Ordenação InternaAnálise de Algoritmos de Ordenação Interna
Análise de Algoritmos de Ordenação Interna
 
Apostila
ApostilaApostila
Apostila
 
Apostila esssa
Apostila   esssaApostila   esssa
Apostila esssa
 
Shell script
Shell scriptShell script
Shell script
 
Focalinux iniciante
Focalinux inicianteFocalinux iniciante
Focalinux iniciante
 
Tutorial ruby
Tutorial rubyTutorial ruby
Tutorial ruby
 
Programming Languages Paradigms
Programming Languages ParadigmsProgramming Languages Paradigms
Programming Languages Paradigms
 

Mehr von Johnnatan Messias

Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...
Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...
Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...Johnnatan Messias
 
Twitter and Youtube Collector
Twitter and Youtube CollectorTwitter and Youtube Collector
Twitter and Youtube CollectorJohnnatan Messias
 
Cálculo Numérico: Interpolação Polinomial com Bubble Sort
Cálculo Numérico: Interpolação Polinomial com Bubble SortCálculo Numérico: Interpolação Polinomial com Bubble Sort
Cálculo Numérico: Interpolação Polinomial com Bubble SortJohnnatan Messias
 

Mehr von Johnnatan Messias (8)

MyShell - English
MyShell - EnglishMyShell - English
MyShell - English
 
Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...
Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...
Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...
 
Twitter and Youtube Collector
Twitter and Youtube CollectorTwitter and Youtube Collector
Twitter and Youtube Collector
 
MyShell
MyShellMyShell
MyShell
 
Quadro de Avisos - IHC
Quadro de Avisos - IHCQuadro de Avisos - IHC
Quadro de Avisos - IHC
 
Lista Encadeada - TP2_AEDSI
Lista Encadeada - TP2_AEDSILista Encadeada - TP2_AEDSI
Lista Encadeada - TP2_AEDSI
 
Simulador Funcional
Simulador FuncionalSimulador Funcional
Simulador Funcional
 
Cálculo Numérico: Interpolação Polinomial com Bubble Sort
Cálculo Numérico: Interpolação Polinomial com Bubble SortCálculo Numérico: Interpolação Polinomial com Bubble Sort
Cálculo Numérico: Interpolação Polinomial com Bubble Sort
 

Kürzlich hochgeladen

637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 anoAdelmaTorres2
 
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptxQUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptxIsabellaGomes58
 
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chaveAula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chaveaulasgege
 
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024HORA DO CONTO4_BECRE D. CARLOS I_2023_2024
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024Sandra Pratas
 
Slides criatividade 01042024 finalpdf Portugues.pdf
Slides criatividade 01042024 finalpdf Portugues.pdfSlides criatividade 01042024 finalpdf Portugues.pdf
Slides criatividade 01042024 finalpdf Portugues.pdfpaulafernandes540558
 
Guia completo da Previdênci a - Reforma .pdf
Guia completo da Previdênci a - Reforma .pdfGuia completo da Previdênci a - Reforma .pdf
Guia completo da Previdênci a - Reforma .pdfEyshilaKelly1
 
Aula 13 8º Ano Cap.04 Revolução Francesa.pptx
Aula 13 8º Ano Cap.04 Revolução Francesa.pptxAula 13 8º Ano Cap.04 Revolução Francesa.pptx
Aula 13 8º Ano Cap.04 Revolução Francesa.pptxBiancaNogueira42
 
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024HORA DO CONTO3_BECRE D. CARLOS I_2023_2024
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024Sandra Pratas
 
Bingo da potenciação e radiciação de números inteiros
Bingo da potenciação e radiciação de números inteirosBingo da potenciação e radiciação de números inteiros
Bingo da potenciação e radiciação de números inteirosAntnyoAllysson
 
Currículo escolar na perspectiva da educação inclusiva.pdf
Currículo escolar na perspectiva da educação inclusiva.pdfCurrículo escolar na perspectiva da educação inclusiva.pdf
Currículo escolar na perspectiva da educação inclusiva.pdfIedaGoethe
 
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...LuizHenriquedeAlmeid6
 
Sociologia Contemporânea - Uma Abordagem dos principais autores
Sociologia Contemporânea - Uma Abordagem dos principais autoresSociologia Contemporânea - Uma Abordagem dos principais autores
Sociologia Contemporânea - Uma Abordagem dos principais autoresaulasgege
 
Recurso Casa das Ciências: Sistemas de Partículas
Recurso Casa das Ciências: Sistemas de PartículasRecurso Casa das Ciências: Sistemas de Partículas
Recurso Casa das Ciências: Sistemas de PartículasCasa Ciências
 
PRIMEIRO---RCP - DEA - BLS estudos - basico
PRIMEIRO---RCP - DEA - BLS estudos - basicoPRIMEIRO---RCP - DEA - BLS estudos - basico
PRIMEIRO---RCP - DEA - BLS estudos - basicoSilvaDias3
 
Educação São Paulo centro de mídias da SP
Educação São Paulo centro de mídias da SPEducação São Paulo centro de mídias da SP
Educação São Paulo centro de mídias da SPanandatss1
 
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...Martin M Flynn
 
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNAS
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNASQUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNAS
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNASEdinardo Aguiar
 
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSOVALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSOBiatrizGomes1
 
geografia 7 ano - relevo, altitude, topos do mundo
geografia 7 ano - relevo, altitude, topos do mundogeografia 7 ano - relevo, altitude, topos do mundo
geografia 7 ano - relevo, altitude, topos do mundonialb
 

Kürzlich hochgeladen (20)

637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
637743470-Mapa-Mental-Portugue-s-1.pdf 4 ano
 
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptxQUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
 
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chaveAula - 2º Ano - Cultura e Sociedade - Conceitos-chave
Aula - 2º Ano - Cultura e Sociedade - Conceitos-chave
 
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024HORA DO CONTO4_BECRE D. CARLOS I_2023_2024
HORA DO CONTO4_BECRE D. CARLOS I_2023_2024
 
Slides criatividade 01042024 finalpdf Portugues.pdf
Slides criatividade 01042024 finalpdf Portugues.pdfSlides criatividade 01042024 finalpdf Portugues.pdf
Slides criatividade 01042024 finalpdf Portugues.pdf
 
Guia completo da Previdênci a - Reforma .pdf
Guia completo da Previdênci a - Reforma .pdfGuia completo da Previdênci a - Reforma .pdf
Guia completo da Previdênci a - Reforma .pdf
 
Aula 13 8º Ano Cap.04 Revolução Francesa.pptx
Aula 13 8º Ano Cap.04 Revolução Francesa.pptxAula 13 8º Ano Cap.04 Revolução Francesa.pptx
Aula 13 8º Ano Cap.04 Revolução Francesa.pptx
 
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024HORA DO CONTO3_BECRE D. CARLOS I_2023_2024
HORA DO CONTO3_BECRE D. CARLOS I_2023_2024
 
treinamento brigada incendio 2024 no.ppt
treinamento brigada incendio 2024 no.ppttreinamento brigada incendio 2024 no.ppt
treinamento brigada incendio 2024 no.ppt
 
Bingo da potenciação e radiciação de números inteiros
Bingo da potenciação e radiciação de números inteirosBingo da potenciação e radiciação de números inteiros
Bingo da potenciação e radiciação de números inteiros
 
Currículo escolar na perspectiva da educação inclusiva.pdf
Currículo escolar na perspectiva da educação inclusiva.pdfCurrículo escolar na perspectiva da educação inclusiva.pdf
Currículo escolar na perspectiva da educação inclusiva.pdf
 
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
Slides Lição 3, Betel, Ordenança para congregar e prestar culto racional, 2Tr...
 
Sociologia Contemporânea - Uma Abordagem dos principais autores
Sociologia Contemporânea - Uma Abordagem dos principais autoresSociologia Contemporânea - Uma Abordagem dos principais autores
Sociologia Contemporânea - Uma Abordagem dos principais autores
 
Recurso Casa das Ciências: Sistemas de Partículas
Recurso Casa das Ciências: Sistemas de PartículasRecurso Casa das Ciências: Sistemas de Partículas
Recurso Casa das Ciências: Sistemas de Partículas
 
PRIMEIRO---RCP - DEA - BLS estudos - basico
PRIMEIRO---RCP - DEA - BLS estudos - basicoPRIMEIRO---RCP - DEA - BLS estudos - basico
PRIMEIRO---RCP - DEA - BLS estudos - basico
 
Educação São Paulo centro de mídias da SP
Educação São Paulo centro de mídias da SPEducação São Paulo centro de mídias da SP
Educação São Paulo centro de mídias da SP
 
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...
DIGNITAS INFINITA - DIGNIDADE HUMANA -Declaração do Dicastério para a Doutrin...
 
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNAS
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNASQUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNAS
QUIZ DE MATEMATICA SHOW DO MILHÃO PREPARAÇÃO ÇPARA AVALIAÇÕES EXTERNAS
 
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSOVALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
VALORES HUMANOS NA DISCIPLINA DE ENSINO RELIGIOSO
 
geografia 7 ano - relevo, altitude, topos do mundo
geografia 7 ano - relevo, altitude, topos do mundogeografia 7 ano - relevo, altitude, topos do mundo
geografia 7 ano - relevo, altitude, topos do mundo
 

Caminhos Mínimos: Dijkstra e Floyd-Warshall

  • 1. Universidade Federal de Ouro Preto Instituto de Ciências Exatas e Biológicas Departamento de Computação TEORIA DOS GRAFOS Primeiro Trabalho Prático Caminhos Mínimos Johnnatan Messias P. Afonso Kayran dos Santos Vítor Mangaravite Professor - Haroldo Gambini Santos Ouro Preto 25 de outubro de 2010
  • 2. Sumário 1 Introdução 1 1.1 Considerações iniciais . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Especicações da máquina . . . . . . . . . . . . . . . . . . . . . . . . 1 1.3 Especicação do problema . . . . . . . . . . . . . . . . . . . . . . . . 1 1.3.1 Material a ser entregue . . . . . . . . . . . . . . . . . . . . . . 1 1.3.2 Documentação impressa incluindo . . . . . . . . . . . . . . . . 2 1.3.3 Regras de Implementação . . . . . . . . . . . . . . . . . . . . 2 1.3.4 Problemas Teste . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3.5 Formato de Entrada e Saída e Parâmetros . . . . . . . . . . . 3 1.4 Dijkstra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.4.1 Heaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.4.2 Aplicação do Algoritmo . . . . . . . . . . . . . . . . . . . . . 5 1.4.3 Versão Preliminar x Final . . . . . . . . . . . . . . . . . . . . 5 1.5 Floyd-Warshall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.5.1 Aplicação do Algoritmo . . . . . . . . . . . . . . . . . . . . . 6 1.5.2 Versão Preliminar x Final . . . . . . . . . . . . . . . . . . . . 6 2 Algoritmo e estruturas de dados 7 2.1 Grafo do Dijkstra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.1.1 Função CriaGrafoPorNome . . . . . . . . . . . . . . . . . . . . 7 2.1.2 Função ConstruindoLista . . . . . . . . . . . . . . . . . . . . . 8 2.1.3 Função AddInteração . . . . . . . . . . . . . . . . . . . . . . . 9 2.2 Heap Binária . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.2.1 Inicialização da heap . . . . . . . . . . . . . . . . . . . . . . . 10 2.2.2 Remove menor . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2.3 Diminui . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2.4 Tamanho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3 Dijkstra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3.1 Função Dijkstra . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3.2 Função DijkstraP . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.3.3 Função Main para o Dijkstra . . . . . . . . . . . . . . . . . . . 14 2.4 Grafo do Floyd-Warshall . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.4.1 Função CriaGrafoPorNome . . . . . . . . . . . . . . . . . . . . 16 2.4.2 Função alocaMatriz . . . . . . . . . . . . . . . . . . . . . . . . 17 2.4.3 Função iniciaMatriz . . . . . . . . . . . . . . . . . . . . . . . . 19 2.4.4 Função iniciaPred . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.5 Floyd-Warshall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.5.1 Função oydP . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.5.2 Função oyd . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.5.3 Função oydPNeg . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.5.4 Função oydNeg . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.5.5 Função imprimirsalvar . . . . . . . . . . . . . . . . . . . . . . 23 2.5.6 Função mainF . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2
  • 3. 3 Testes 27 3.1 Exemplo de teste para o Floyd-Warshall . . . . . . . . . . . . . . . . 27 3.1.1 Grafo com Peso Positivo . . . . . . . . . . . . . . . . . . . . . 27 3.1.2 Grafo com Peso Negativo . . . . . . . . . . . . . . . . . . . . . 29 3.2 Testes em massa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.2.1 Floyd-Warshall . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.2.2 Dijkstra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 4 Conclusão 36 Lista de Figuras 1 Figura Repres. Alocação Matriz . . . . . . . . . . . . . . . . . . . . . 18 2 Figura Grafo com Peso Positivos . . . . . . . . . . . . . . . . . . . . 27 3 Figura Matriz Dist . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 4 Figura Matriz Pred . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 5 Figura Exemplo de Caminho . . . . . . . . . . . . . . . . . . . . . . . 28 6 Figura Grafo com Peso Negativo . . . . . . . . . . . . . . . . . . . . . 29 7 Figura Matriz Dist . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 8 Figura Matriz Pred . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 9 Figura Exemplo de Caminho Neg . . . . . . . . . . . . . . . . . . . . 30 10 Graco para Floyd-Warshall sobre o grafo rg300_768 . . . . . . . . . 31 11 Graco para Floyd-Warshall sobre o grafo rg300_4730 . . . . . . . . 32 12 Graco para Floyd-Warshall sobre o grafo comp-2007-2-22c . . . . . . 33 13 Graco para Dijkstra sobre o grafo rome99c . . . . . . . . . . . . . . 34 14 Graco para Dijkstra sobre o grafo USA-road-d-NYc . . . . . . . . . 35 Lista de Programas 1 Algoritmo Floyd Warshall C . . . . . . . . . . . . . . . . . . . . . . . 5 2 TAD Grafo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3 Função CriaGrafoPorNome para o dijkstra . . . . . . . . . . . . . . . 7 4 Função ConstruindoLista . . . . . . . . . . . . . . . . . . . . . . . . . 8 5 Função ConstruindoLista . . . . . . . . . . . . . . . . . . . . . . . . . 9 6 TAD Grafo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 7 Criação da heap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 8 Inicialização da heap . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 9 Remove Menor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 10 Decrementa Chave . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 11 Tamanho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 12 Fijkstra sem Impressão . . . . . . . . . . . . . . . . . . . . . . . . . . 12 13 Dijkstra com Impressão . . . . . . . . . . . . . . . . . . . . . . . . . . 13 14 Programa principal do Dijkstra . . . . . . . . . . . . . . . . . . . . . 14 15 TAD Grafo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 16 Função criagrafopornome . . . . . . . . . . . . . . . . . . . . . . . . . 16 17 Função alocaMatriz . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 18 Função iniciamatriz . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3
  • 4. 19 Função iniciaPred . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 20 Função oydP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 21 Função oyd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 22 Função oydPNeg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 23 Função oydNeg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 24 Função imprimirsalvar . . . . . . . . . . . . . . . . . . . . . . . . . . 23 25 Função mainF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 26 Programa de Teste . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Lista de Tabelas 1 Instâncias de teste e algoritmos a executar . . . . . . . . . . . . . . . 2 4
  • 5. 1 Introdução A computação tem como base a resolução de problemas que até então não havia soluções disponíveis bem como para soluções rápidas para o mesmo problema. Assim, cabe ao Cientista da Computação identicar soluções para a resolução dos problemas, principalmente, tornando-os otimizados e rápidos. Através desses conceitos coube ao grupo utilizar os conceitos de Teoria dos Grafos para a modelagem do trabalho. Na teoria de grafos, o problema do caminho mínimo consiste na minimização do custo de travessia de um grafo entre dois nós (ou vértices). Custo este dado pela soma dos pesos de cada aresta percorrida. Formalmente, dado um grafo valorado (ou seja, um conjunto V de vértices, um conjunto A de arestas e uma função de peso f : A → R) e, dado qualquer elemento v ∈V, encontrar um caminho P de v para cada v ∈ V tal que p∈P f (p) é mínimo entre todos os caminhos conectando n a n. 1.1 Considerações iniciais • Ambiente de desenvolvimento do código fonte: Microsoft Visual Studio C 10.0, NetBeans 6.9.1. • Compilador: gcc 4.4.5. • Linguagem utilizada: Linguagem C. • Ambiente de desenvolvimento da documentação: TeXnicCenter 1 BETA 7.50- A Editor de L T X, Editor dos grafos: R-2.12.0 for windows. E 1.2 Especicações da máquina • Intel Pentium IV 3.0 GHz, 64 bits • Memória: 2 GB • Ubuntu 10.10 AMD 64, kernel 2.6.35-22 generic 1.3 Especicação do problema 1.3.1 Material a ser entregue Código em C, incluindo instruções para compilação. Essas instruções podem, por exemplo, indicar opções que devem ser usadas na compilação do código em C. (ex.: -O2 -ast-math). Devem ser oferecidas as seguintes implementações: • Algoritmo de Dijkstra para para computação de c.m. de uma fonte para todos os outros vértices; → a fonte deve ser sorteada com a função rand a cada execução do algoritmo de Dijkstra dentro do programa. 1
  • 6. Algoritmo Floyd-Warshall (FW) para computação dos caminhos mínimos de todos os vértices para todos os outros do grafo; → a implementação de FW deve incluir um teste para a existência de ciclos de custo negativo no grafo. Caso um seja encontrado, o algoritmo deve concluir imediatamente sua execução e indicar o ciclo encontrado. 1.3.2 Documentação impressa incluindo • explicação da implementação, incluindo referências bibliográcas; • tabelas contendo os resultados dos experimentos realizados 1.3.3 Regras de Implementação Os códigos devem ser escritos em C, sem o uso de bibliotecas adicionais, exceto a biblioteca padrão da linguagem ou da biblioteca GNU. Os seguintes padrões* C são aceitos: • ANSI C 89 • ANSI C 99 • GNU C *O compilador GCC permite a compilação com validação de códigos com a ag -std. Ex.: (-std=c99). Códigos com vazamento de memória ou problemas do tipo serão penalizados com -1 pontos. Os códigos serão testados com a ferramenta valgrind. 1.3.4 Problemas Teste Instância Vértices Arestas Testar rome99c.gr 3.353 8.859 Dijkstra USA-road-d.NYc.gr.bz2 264.346 730.100 Dijkstra rg300_768.gr 300 768 Floyd-Warshall rg300_4730.gr 300 4.730 Floyd-Warshall comp-2007-2-22c.gr.gz 600 276.666 Floyd-Warshall Tabela 1: Instâncias de teste e algoritmos a executar • soluções devem ser checadas; caminhos mínimos pré-computados para rome99: spathsRome99c.gr.bz2 (lembre-se que entre dois nós pode haver mais de um caminho ótimo possível). outros: nspathsRg300_768.txt.bz2 . • alguns problemas vieram da competição do DIMACS. • os problemas teste para o algoritmo Floyd-Warshall (FW) podem incluir val- ores negativos nos custos dos arcos. A implementação de FW, quando encon- trar um ciclo de custo negativo, deve abortar a computação e como saída deve somente indicar o caminho que indica o ciclo de custo negativo encontrado. * 2
  • 7. 1.3.5 Formato de Entrada e Saída e Parâmetros O programa deve receber os seguintes argumentos, quando chamado pela linha de comando: prog arquivoProblema nrExecuções flagDepuração Onde flagDepuração pode receber valor 0 ou 1. Como exemplo: prog rome99.gr 1000 1 Indica que o programa irá ler o grafo do arquivo rome99.gr, executando o algo- ritmo de caminhos mínimos 1000 vezes e ao nal irá imprimir/salvar informação de depuração. A informação de depuração que deve ser gerada, quando solicitada, é a seguinte: arquivo spaths.txt O arquivo spaths.txt deve conter todos os caminhos mínimos computados para cada par de vértices (s,t), sendo s diferente de t . Cada linha contém a informação sobre o caminho mínimo de um par (s,t), no formato: [s,t](dist) n1 n2 n3 ... nn Onde: • s: nó fonte • t: nó destino • dist: distância calculada entre s e t • n1 n2 n3 ... nn: caminho computado entre s e t, incluindo todos os nós intermediários no formato: s n2 n3 ... t 1.4 Dijkstra O algoritmo de dijkstra para caminhos mínimos foi feito por Edsger W. Dijkstra em 1956 e foi publicado em 1959. Este algoritmo é um algoritmo de busca em grafos que resolve o problema de caminhos mínimos para grafos sem ciclos de custo negativo [5]. O algoritmo de dijkstra é um algoritmo guloso, pois toma uma decisão que parece ser a melhor no momento. Dado um nó fonte ele calcula o caminho de menor distancia deste nó a todos os outros. Ele funciona semelhante ao BFS, porém trata grafos com peso. Ele trata os nós mais próximos da fonte primeiro, porém essa proximidade se refere ao peso entre as arestas e não ao número de arestas percorridas. Sua complexidade é O((|E| + |V |)log|V |)[5]. Para a execução do algoritmo são utilizados dois vetores auxiliares (dist e pred) com tamanho igual ao numero de vértices do grafo. O vetor dist armazenará as distancias do nó fonte até qualquer nó do grafo. O vetor pred armazenará os anteriores de cada nó no caminho da fonte até ele. Além disso é necessária uma heap para saber a ordem de processamento dos nós. Ao inicio da execução do algoritmo o vetor de distancias é inicializado com innito para todos os vértices, exceto o nó fonte s que terá distancia 0. O vetor pred será todo inicializado com nulo. O algoritmo processa todos os nós da heap. Enquanto ainda há nós na heap retira-se o menor vértice (u) e, para cada vizinho v vértice verica se a distancia até v passando por u é menor que a distancia até v já calculada. Caso seja menor u é marcado como antecessor de v no vetor pred e a distancia 3
  • 8. até v é alterada para a distancia até u mais a distancia entre u e v, atualizando a heap com a nova distancia. As operações que são mais custosas para o algoritmo do dijkstra são as operações sobre a heap, portanto uma escolha errada de heap pode causar ineciência do algoritmo. 1.4.1 Heaps Heaps são las de prioridade implementadas baseadas em árvores. Existem ba- sicamente dois tipos de heap, a heap de máximo, em que para cada nó x na arvore, x tem chave maior que de todos seus lhos[2], e a heap de mínimo que é utilizada no algoritmo de dijkstra, em que cada nó x pai sempre é menor que todos seus lhos. As heaps para o dijkstra possuem como chave os valores de distancia do vértice fonte até os respectivos nós. A medida que a distancia encontrada diminui para cada nó, sua prioridade aumenta e sua vez de ser processado se aproxima, congurando uma heap de mínimo. As funções básicas de uma heap qualquer são: • Inserção • deleção de menor • decremento da chave Heaps de Fibonacci: Para a versão nal foi feita uma tentativa de implementação da heap de bonacci[7]. As heaps de bonacci são coleções de árvores ordenadas como heaps mínimos[6]. As heaps de bonacci são implementadas usando listas circulares duplamente encadeadas[1]. A heap é composta da lista de raízes e para cada nó da lista de raízes tem uma lista de lhos que também pode ter seus lhos, assim em diante. A heap também tem um ponteiro para o menor nó da lista. A inserção na heap de bonacci apenas insere o novo nó na lista de raízes. A inserção verica se o novo nó é menor que o menor atual, caso seja o menor passa a ser o novo. Esse procedimento é executado com custo real O(1). Na função de extração do menor nó, o nó apontado por min é removido da lista de raízes e todos seus lhos são inseridos na lista de raízes. Depois a heap é consolidada, o que signica que todas as raízes terão grau (numero de lhos na lista) diferente. Caso haja mais de um nó com um certo grau, o maior deles vira lho do outro. A menor das raízes passa a ser o novo min. O custo amortizado da função de extração de menor é O(logn). A diminuição da chave pode fazer com que um lho que menor que seu pai, ferindo a propriedade das heaps. Caso isso ocorra este nó é cortado do pai e levado à lista de raízes. Caso o pai seja lho de outro nó e já tenha perdido um lho sendo lho desde que virou lho de seu nó pai, ele também será cortado de seu pai e virará raiz da heap, senão apenas será marcado para ser cortado se perder mais lhos. Se o nó decrementado for menor que a raiz, este passará a ser o novo minimo. O custo amortizado desta função é O(1). As heaps de bonacci possuem uma estrutura muito complexa, contendo listas circulares duplamente encadeadas. Isso dicultou bastante a implementação não permitindo que fosse encerrada a versão do dijkstra usando essas heaps em tempo 4
  • 9. hábil, pois para cada nó há apontador para seu pai, seu irmão da esquerda, seu irmão da direita e todos seus lhos. Acredita-se que essas heaps poderiam melhorar ainda mais o algoritmo do dijkstra devido à sua boa complexidade. Com as heaps 2 binarias a ordem de complexidade do dijkstra se aproxima muito de O(n logn), com 2 heaps de bonacci essa complexidade aproximaria O(n ). 1.4.2 Aplicação do Algoritmo 1.4.3 Versão Preliminar x Final Para o problema proposto a cada nó da heap é representado pelo índice de seu vértice no grafo, índice esse que é usado para a identicação da distancia do nó no vetor dist, valor este que é a chave do nó. A função diminui recebe o índice do nó que foi alterado, porém não é conhecido seu posicionamento na heap. Para saber qual nó da heap foi alterado de inicio foi feita uma busca linear O(n) em todo o vetor da heap, versão que foi enviada na preliminar da competição. Para a versão nal essa busca linear foi substituída pela busca em hash que é O(1). Como os possíveis valores da heap são conhecidos (1 até n) e também seu tamanho máximo (n), foi possível fazer um hash mínimo perfeito. Para isso foi criado um novo vetor pos, que para cada posição i deste vetor, seu valor corresponde à posição do vértice i do grafo no vetor da heap. 1.5 Floyd-Warshall O algoritmo de Floyd-Warshall tem como objetivo calcular a menor distância de todos os vértices do grafo para todos os demais, recebendo, para isso, uma matriz de adjacências representando o grafo. Com ordem de complexidade cúbica assume que para percorrer o caminho A→C haverá um caminho A → B e B → C , isto é, para qualquer par de vértices (i, j) ∈ V , considera-se todos os caminhos de iaj cujos vértices intermediários pertencem ao subconjunto 1, 2, 3..., k , e p como o mais curto de todos eles. Em resumo: dist(i; j; k): o comprimento do caminho mais curto entre i e j tal que apenas os nós 1, ..., k podem ser usados como intermediários. No Programa 1 temos o algoritmo implementado em C. void ∗ ∗∗ int f l o y d ( TGrafo g , TVertice auxMatriz ) { int ∗∗ k, i , j ; pred ; pred = NULL ; 5 −q t d V e r t ) ) ; for pred = i n i c i a P r e d ( pred ,( g −q t d V e r t ; i ++) for ( i =0; i g ( j = 0 ; j g− q t d V e r t ; j ++) a u x M a t r i z [ i ] [ j ] = g− for m a t r i z [ i ] [ j ] ; ( k = 0 ; k g− for q t d V e r t ; k++) 10 i g− for ( i = 0; q t d V e r t ; i ++) j g− if ( j = 0; q t d V e r t ; j ++) ( ( auxMatriz [ i ] [ k ] . peso + auxMatriz [ k ] [ j ] . peso ) auxMatriz [ i ] [ j ] . peso ) { auxMatriz [ i ] [ j ] . peso = auxMatriz [ i ] [ k ] . peso + auxMatriz [ k ] [ j ] . peso ; if pred [ i ] [ j ] = pred [ k ] [ j ] ; 15 ( auxMatriz [ i ] [ i ] . peso 0) { 5
  • 10. return ; } } f r e e ( pred [ 0 ] ) ; 20 f r e e ( pred ) ; } Programa 1: Algoritmo Floyd Warshall C 1.5.1 Aplicação do Algoritmo O algoritmo de Floyd-Warshall pode ser utilizado para os seguintes problemas: • Caminhos mais curtos em grafos orientados (algoritmo de Floyd); • Proximidade transitiva de grafos orientados (algoritmo de Warshall); • Encontrar uma expressão regular denotando a linguagem regular aceita por um autômato nito (algoritmo de Kleene); • Inversões de matrizes de números reais (algoritmo de Gauss-Jordan); • Roteamento otimizado. Nesta aplicação, o objetivo é encontrar o caminho com o máximo uxo entre dois vértices. Isto signica que, em vez de calcular o mínimo, calcula-se o máximo; • Testar se um grafo não-orientado é bipartido. 1.5.2 Versão Preliminar x Final Reinicialização das Matrizes: • Preliminar: Na versão preliminar havia um erro no algoritmo de modo que as matrizes de distâncias e dos predecessores não eram reinicializadas quando o usuário passava como argumento um número inteiro superior a uma execução. Através disso as matrizes não eram reinicializadas a partir da 1 execução. Esse problema afetava a execução do programa somente quando não havia impressão ou quando o número de execuções fosse superior a 1 (um). • Final: Para melhorar o desempenho bem como corrigir o problema anterior alocamos tanto a matriz de distâncias quanto a dos predecessores antes de chamar a função do algoritmo Floyd-Warshall e desalocando no nal da ex- ecução de todo o programa, assim possibilitou em um ganho de desempenho quando levarmos em consideração a alocação das matrizes. Um ponto importante a ser citado é que mesmo não alocando e desalocando a todo execução sempre reinicializamos as duas matrizes. Isso pode ser percebido no Programa 17 Tratamento do Ciclo Negativo: • Preliminar: Não havia uma otimização no tratamento de ciclos negativos, assim, em cada execução o algoritmo vericava se havia ou não ciclos negativos no grafo. 6
  • 11. Final: Para otimizar o tratamento de ciclos negativos foi incluída na estrutura 15 do grafo uma variável ehcicloNeg que verica na entrada de arquivos, vide Programa 16, se no grafo continha ou não peso negativo. Através dessa veri- cação, para otimizar, criamos diferentes funções para o algoritmo de Floyd- Warshall, sendo para grafos com ciclos negativos: oydPNeg, oydNeg, vide Programas 22, 23 respectivamente . E para positivos: oydP, oyd, vide Programas 20, 21 respectivamente. Nessas funções não realizamos a vericação para caso haja ciclo negativo uma vez que o grafo não contém determinado ciclo[3]. Obs.: Na Seção 2.4 explicaremos melhor esse método. 2 Algoritmo e estruturas de dados 2.1 Grafo do Dijkstra O grafo para o algoritmo de dijkstra foi representado pela lista de adjacências apresentada na estrutura 2 #include s t d a f x . h typedef struct int { qtdusada , ∗ resultado ; 5 } Caminho ; typedef struct int ∗ { vizinhos , ∗ pesos , qtdAlloc , qtdFree ; } TVertice ; 10 typedef struct int { qtdVert , qtdMedia ; TVertice ∗ v; } TGrafo ; 15 TGrafo cria_grafo_por_nome ( char ∗ ) ; void i m p r i m i r _ s a l v a r ( Caminho ∗) ; 20 void construindoLista ( int ∗ int ∗, , TGrafo ∗) ; void addInteracao ( int ∗ int ∗ , , TGrafo ∗, int ∗ ) ; Programa 2: TAD Grafo 2.1.1 Função CriaGrafoPorNome A Função CriaGrafoPorNome tem como objetivo fazer a leitura do grafo a partir de um arquivo .txt e iniciar a lista de adjacências bem como instanciar a lista com todos arcos do grafo de um vértice A para um vértice B. Vide Programa 3 TGrafo cria_grafo_por_nome ( char ∗ nome ) { 7
  • 12. ∗ arqE ; char FILE ∗ buf , ∗ tok ; 5 int TGrafo g; char ∗ sizeof char numArestas , numVertices , vA , vB , peso , media_qtd_arestas ; buf = ( ) malloc ( ( ) ∗ BUFSIZ ) ; arqE = f o p e n ( nome , r) ; 10 if ( ! arqE ) { printf ( Erro ao a b r i r o a r q u i v o de e n t r a d a %s , nome ) ; g . q t d V e r t = − 1; return (g) ; while } 15 ( ! f e o f ( arqE ) ) { if buf = f g e t s ( buf , BUFSIZ , arqE ) ; break ( buf == NULL) ; 20 switch case ' p ' ( buf [ 0 ] ) { : tok = ) ; s t r t o k ( buf , tok = s t r t o k (NULL, ) ; tok = s t r t o k (NULL, ) ; 25 numVertices = a t o i ( tok ) ; tok = s t r t o k (NULL, ) ; numArestas = a t o i ( tok ) ; media_qtd_arestas = numArestas / numVertices + 1; break c o n s t r u i n d o L i s t a ( n u m V e r t i c e s , m e d i a _ q t d _ a r e s t a s , g ) ; 30 case ; 'a ' : tok = s t r t o k ( buf , ) ; tok = s t r t o k (NULL, ) ; vA = a t o i ( tok ) ; 35 tok = s t r t o k (NULL, ) ; vB = a t o i ( tok ) ; tok = s t r t o k (NULL, ) ; peso = a t o i ( tok ) ; break a d d I n t e r a c a o (vA , vB , g , p e s o ) ; 40 default ; break : ; } } 45 f c l o s e ( arqE ) ; return f r e e ( buf ) ; (g) ; } Programa 3: Função CriaGrafoPorNome para o dijkstra 2.1.2 Função ConstruindoLista A Função ConstruindoLista tem como objetivo inicializar a lista de adjacências para todos os nós. Vide Programa 4 void int ∗ int ∗ ∗ int construindoLista ( qtdV , m ed ia , TGrafo g) { i ; g−q t d M e d i a = ∗ m e d i a ; g−q t d V e r t = ∗ qtdV ; 8
  • 13. 5 −v ∗ ) c a l l o c ( ∗ qtdV , sizeof for g = ( TVertice ( TVertice ) ) ; ( i = 0; i ∗ qtdV ; i ++) { g−v [ i ] . qtdAlloc = 0; −v [ ∗ media ; int sizeof int g i ] . qtdFree = g− ∗ ) c a l l o c ( ∗ me d ia , int sizeof int v [ i ]. vizinhos = ( ( )) ; 10 g−v [ i ]. pesos = ( ∗ ) c a l l o c ( ∗ m ed ia , ( )) ; } } Programa 4: Função ConstruindoLista 2.1.3 Função AddInteração A função AddInteração adiciona a interação lida do arquivo ao nó de origem da mesma. Vide Programa 5 void ∗ vA , int int ∗ vB , T G r a f o ∗ g , ∗ peso ) { int if addInteracao ( (!g−v [ ( ∗ vA ) − 1 ] . q t d F r e e ) { g−v [ ( ∗ vA ) − 1 ] . q t d F r e e + = g− int q t d M e d i a ; g−v [ ( ∗ vA ) − 1 ] . p e s o s = ( ∗ ) r e a l l o c ( g−v [ ( ∗ vA ) − 1 ] . p e s o s , sizeof int ( ) ∗ ( g− v [ ( ∗ vA ) − 1 ] . q t d F r e e + g− v [ ( ∗ vA ) − 1 ] . int qtdAlloc ) ) ; 5 −v [ ( ∗ vA ) − ∗ ) r e a l l o c ( g−v [ ( ∗ vA ) − 1 ] . sizeof int g 1 ] . vizinhos = ( vizinhos , ( ) ∗ ( g−v [ ( ∗ vA ) − 1 ] . q t d F r e e + g−v [ ( ∗ vA ) − 1 ] . qtdAlloc ) ) ; } g−v [ ( ∗ vA ) − 1 ] . vizinhos [ g −v [ ( ∗ vA ) − 1 ] . qtdAlloc ] = ( ( ∗ vB ) − 1) ; g−v [ ( ∗ vA ) − 1 ] . pesos [ g −v [ ( ∗ vA ) − 1 ] . q t d A l l o c ++] = ∗ peso ; g−v [ ( ∗ vA ) − 1 ] . q t d F r e e −−; 10 } Programa 5: Função ConstruindoLista 2.2 Heap Binária A heap binaria é representada por uma árvore binária completa ou quase com- pleta. Para o caso do dijkstra, como a heap é mínima, o pai sempre é menor que seus lhos. Para representar a heap há duas estruturas possíveis, lista encadeada com ponteiros para os dois lhos e lista simples utilizando um vetor[8]. Na imple- mentação foi utilizada a segunda estrutura por ser mais simples de trabalhar. Vide Programa 6: #include TGrafoD . h typedef struct int ∗ ∗ Heap { v,∗ dist , pos , qtdV ; 5 } THeap ; int tamanho ( THeap ∗) ; void c r i a H e a p ( THeap int ∗ ∗, ) ; 10 void reconstroi ( int int , , THeap ∗) ; void c o n s t r o i ( THeap ∗) ; 9
  • 14. 15 int p e g a r M e n o r ( THeap ∗) ; void d i m i n u i ( THeap ∗, int ∗ ) ; Caminho d i j k s t r a P ( TGrafo ∗, int ∗ ) ; 20 void d i j k s t r a ( TGrafo ∗, int ∗ ) ; Programa 6: TAD Grafo Para representar uma árvore com vetor considera-se que para o vértice i seus lhos são (2 ∗ i + 1) e (2 ∗ i + 2), sendo sua raiz o nó de índice 0. O pai de um nó de índice i é representado pelo nó de índice ceil(i/2). 2.2.1 Inicialização da heap A função Criaheap 7 aloca todas os vetores da heap e inicializa seus valores para os esperados ao inicio do dijkstra. void ∗ int ∗ int c r i a H e a p ( THeap h, qtdD ) { i ; − ∗ qtdD ; int sizeof int h qtdV = − ∗ ) c a l l o c ( ∗ qtdD , int sizeof int h v = ( ( )) ; 5 h− d i s t = ( ∗ ) c a l l o c ( ∗ qtdD , int sizeof int ( )) ; h− ∗ ) c a l l o c ( ∗ qtdD , for p o s = ( ( )) ; ( i = 0; i ∗ qtdD ; i ++) { h− d i s t [ i ] = INF ; h− v [ i ] = i ; 10 h− p o s [ i ] = i ; } } Programa 7: Criação da heap A Inserção para a heap binária consiste em colocar sua chave no vetor e refazer o posicionamento do nós no vetor seguindo os índices de forma a respeitar a pro- priedade da heap de que o pai é menor que todos os lhos. A ordem de complexidade da inserção é O(logn)[8]. Para o caso do dijkstra todos os nós são inseridos na heap logo no começo, para isso existe a função constrói que considera que as n/2 últimas posições do vetor já estão na heap, já que nenhuma posição representa o pai de outra já que i é pai de 2∗i+1 e 2∗i+2 e i é pai de n+1 e n+2, para i = n/2. Considerando isso os n/2 primeiros nós são inseridos na heap pela função reconstrói que verica a propriedade da heap, trocando o pai com seu menor lho, caso o lho seja menor que o pai. Na teoria são feitas n/2 inserções na heap, o que gera uma complexidade O(nlogn)[2]. Vide Programa 8 void ∗ int c o n s t r o i ( THeap h) { esq ; − while esq = h qtdV / 2; ( e s q = 0) { 5 r e c o n s t r o i ( esq , − h qtdV − 1, h) ; esq −−; } } 10 void reconstroi ( int esq , int dir , THeap ∗h ) { 10
  • 15. int int i = esq ; int j ; aux ; j = i ∗ 2 + 1; 15 − while aux = h v [ i ] ; if ( j = dir ) { if ( j dir ) − ( h d i s t [ h v [ j ] ]− − − h d i s t [ h v [ j + 1]]) if j ++; 20 − − − break ( h d i s t [ aux ] = h d i s t [ h v [ j ] ] ) ; − h p o s [ h v [ j ] ] − = i ; − h v [ i ] − = h v [ j ] ; i = j ; 25 j = i ∗ 2 + 1; } − h p o s [ aux ] = i ; − h v [ i ] = aux ; } Programa 8: Inicialização da heap 2.2.2 Remove menor A remoção do menor é feita pegando sua chave e o trocando com o ultimo elemento válido do vetor, que será a folha extrema direita da árvore. Após isso a heap é refeita com a função reconstrói desconsiderando a posição onde estava o ultimo. Sua complexidade é O(logn)[8].Vide Programa 8 int ∗ int p e g a r M e n o r ( THeap h) { min ; − min = h v [ 0 ] ; − h v [ 0 ] = h− v [( −− h−qtdV ) ]; 5 h− p o s [ h− v [ 0 ] ] = 0 ; r e c o n s t r o i ( 0 , h− qtdV − 1 , return h) ; min ; } Programa 9: Remove Menor 2.2.3 Diminui Para decrementar a chave, já que o dijkstra já altera o valor do vetor dist, a função apenas verica se o elemento com chave alterada fere a propriedade da heap e o troca com seu pai em caso armativo. Isso é feito até que a propriedade volte a ser obedecida pelo nó alterado. Vide Program 10 void ∗h , int ∗ int d i m i n u i ( THeap i ) { aux , pos ; pos − = h p o s [ ∗ i ]; 5 while ( ( p o s ) = 1 − h d i s t [ h v [ ( − int ) c e i l ( ( pos ) / 2.) − 1]] h − d i s t − int [ h v [ ( p o s ) ] ] ) { aux = h−v [ ( ) c e i l ( ( pos ) / 2.) − 1]; 11
  • 16. int − − int int h v [ ( ) c e i l ( ( pos ) / 2.) 1] = h v [ ( p o s ) ] ; 10 − h p o s [ h v [ ( − ) c e i l ( ( pos ) / 2.) − 1]] = ( ) c e i l ( ( pos ) / 2.) − 1; − h v [ ( p o s ) ] = aux ; − int h p o s [ aux ]= p o s ; pos = ( ) c e i l ( ( pos ) / 2.) − 1; } 15 } Programa 10: Decrementa Chave 2.2.4 Tamanho Esta função apenas retorna o tamanho da heap. Usada para vericar a existencia de elementos na heap. Vide Programa 11 int ∗ return tamanho ( THeap h) { − h qtdV ; } Programa 11: Tamanho 2.3 Dijkstra 2.3.1 Função Dijkstra Essa função é responsável pela simples execução do algoritmo de Dijkstra sem impressão de caminho. void d i j k s t r a ( TGrafo ∗ g , int ∗ s) { int THeap h; v, u, i , ∗ prev ; 5 prev = ( int ∗ ) calloc (g −q t d V e r t , sizeof int ( )) ; c r i a H e a p (h , (g −q t d V e r t ) ) ; h. dist [ ∗s] = 0; c o n s t r o i (h ) ; 10 while ( tamanho (h ) ) { for v = p e g a r M e n o r (h ) ; ( i = 0; i g −v [ v ] . qtdAlloc ; i ++) { −v [ v ] . if u = g vizinhos [ i ] ; (h . dist [ u ] h. dist [v] + g −v [ v ] . pesos [ i ] ) { 15 h. dist [u] = h. dist [v] + g −v [ v ] . pesos [ i ] ; prev [ u ] = v; d i m i n u i (h , u ) ; } } 20 } free (h . dist ) ; free (h . v) ; f r e e ( prev ) ; } Programa 12: Fijkstra sem Impressão 12
  • 17. 2.3.2 Função DijkstraP Essa função é responsável pela execução do algoritmo de Dijkstra imprimindo de caminho. O caminho que é calculado para cada vertice v percorrendo o vetor pred iniciando pelo pred[v] seguindo pelo pred até que ele seja igual ao nó fonte do dijkstra. Vide Programa 13 Caminho d i j k s t r a P ( TGrafo ∗ g , int ∗ s) { THeap h; Caminho c ; ∗ int FILE arq ; 5 v, w, u, aux , ∗ prev , i ; prev = ( int ∗ ) calloc (g −q t d V e r t , sizeof int ( )) ; c r i a H e a p (h , (g −q t d V e r t ) ) ; h. dist [ ∗s] = 0; 10 c o n s t r o i (h ) ; for (u = 0; u g−q t d V e r t ; u++) { 15 prev [ u ] = − 1; while } ( tamanho (h ) ) { for v = p e g a r M e n o r (h ) ; ( i = 0; i g−v [ v ] . qtdAlloc ; i ++) { 20 −v [ v ] . if u = g vizinhos [ i ] ; (h . dist [ u ] h. dist [v] + g −v [ v ] . pesos [ i ] ) { h. dist [u] = h. dist [v] + g −v [ v ] . pesos [ i ] ; prev [ u ] = v; d i m i n u i (h , u ) ; 25 } } } w = INF ; 30 for (u = 0; u g −q t d V e r t ; u++) { free (g −v [ u ] . pesos ) ; f r e e ( g−v [ u ] . vizinhos ) ; } arq = fopen ( s p a t h s . t x t , w ) ; 35 if ( ! arq ) { Erro ao e s c r e v e r no a r q u i v o ) ; return printf ( ; int ∗ sizeof int } 40 ∗ ( g−q t d V e r t +1) ) ; for c . resultado = ( ) malloc ( ( ) −q t d V e r t ; if (u = 0; u g u++) { ∗s continue (u == || h . d i s t [ u]== w) ; c . qtdusada = 2; 45 c . resultado [ 0 ] = h. dist [u ] ; c . resultado [ 1 ] = u; while aux = prev [ u ] ; ( aux != ∗s aux != −1) { c . r e s u l t a d o [ c . q t d u s a d a ++] = aux ; 50 aux = p r e v [ aux ] ; } 13
  • 18. c . r e s u l t a d o [ c . qtdusada ] = ∗s ; [%d,%d ](% d ) , ( ∗ s ) +1 , u +1 , c . r e s u l t a d o for f p r i n t f ( arq , [0]) ; ( i = c . qtdusada ; i 0 ; i −−){ 55 f p r i n t f ( a r q , %d , c . r e s u l t a d o [ i ] + 1 ) ; } f p r i n t f ( arq , n ) ; } free ( c . resultado ) ; 60 free (h . dist ) ; free (h . v) ; −v ) ; return free (g c ; } Programa 13: Dijkstra com Impressão 2.3.3 Função Main para o Dijkstra Essa função efetua as chamadas para leitura de arquivos e execução do dijkstra. Note que foi feito uso de uma técnica denominada Loop Unrolling para aproveitarmos melhor o uso do Pipeline do processador[4], ganhando uma leve melhora no tempo de execução do programa. #include T D i j k s t r a . h int int main ( char ∗∗ argc , argv ) { 5 int flagDepuracao , nrExecucao , vertRand ; TGrafo g; if Caminho c ; ( argc 3) { C o n f i r a o numero de parametros ) ; return printf ( 10 ( EXIT_FAILURE ) ; } srand ( 0 ) ; flagDepuracao = a t o i ( argv [ 3 ] ) ; nrExecucao = a t o i ( argv [ 2 ] ) ; 15 if g = cria_grafo_por_nome ( a r g v [ 1 ] ) ; ( g . qtdVert = = − 1) { n ∗∗ Erro ao c r i a r o g r a f o ) ; return printf ( ( EXIT_FAILURE ) ; 20 switch } case ( flagDepuracao ) { switch 0: case ( nrExecucao % 4) { while 0: 25 ( nrExecucao ) { vertRand = rand ( ) % g . qtdVert ; d i j k s t r a (g , v e r t R a n d ) ; nrExecucao −−; 30 vertRand = rand ( ) % g . qtdVert ; d i j k s t r a (g , v e r t R a n d ) ; nrExecucao −−; vertRand = rand ( ) % g . qtdVert ; 14
  • 19. 35 d i j k s t r a (g , v e r t R a n d ) ; nrExecucao −−; vertRand = rand ( ) % g . qtdVert ; d i j k s t r a (g , v e r t R a n d ) ; 40 nrExecucao −−; break } case ; while 2: ( nrExecucao ) { 45 vertRand = rand ( ) % g . qtdVert ; d i j k s t r a (g , v e r t R a n d ) ; nrExecucao −−; vertRand = rand ( ) % g . qtdVert ; 50 d i j k s t r a (g , v e r t R a n d ) ; nrExecucao −−; break } ; 55 default while : ( nrExecucao −−) { vertRand = rand ( ) % g . qtdVert ; d i j k s t r a (g , v e r t R a n d ) ; break } 60 ; break } case ; 1: 65 vertRand = 0; c = d i j k s t r a P (g , v e r t R a n d ) ; } return ( EXIT_SUCCESS ) ; 70 } Programa 14: Programa principal do Dijkstra 2.4 Grafo do Floyd-Warshall Para a representação do grafo utilizamos a estrutura TGrafo 15, onde temos uma variável ehcicloNeg para a vericação se o grafo é negativo ou não bem como qtdVert, qtdAres para a quantidade de vértices e arestas respectivamente. O grafo, na verdade, é representado por uma matriz de adjacências do tipo TVertice** matriz, contendo um peso (distância) de um vértice A para um vértice B. Isso pode ser visto facilmente no Programa 15. Além de calcular a distância e a matriz de predecessores, para a impressão dos caminhos de todos os vértices para todos os demais, foi preciso utilizar a estrutura Caminho, onde qtdTotal, neg, s, t representam a quantidade total de vértices do grafo, vericação se o grafo é ou não negativo para a geração do caminho de ciclo negativo, s e t os vértices de início e nal do grafo, respectivamente. E, ainda, o resultado contendo a quantidade de vértices que fazem parte do caminho gerado e o próprio caminho de um vértice A para um vértice B. Isso pode ser visto na Figura 5 15
  • 20. #include s t d a f x . h typedef struct int ∗ { TP , qtdNos ; 5 } TPasseio ; typedef struct { ∗ int TPasseio resultado ; qtdTotal , neg , s , t ; 10 } Caminho ; typedef struct int { peso ; } TVertice ; 15 typedef struct int { short int qtdVert , qtdAres ; ehcicloNeg ; TVertice ∗∗ matriz ; 20 } TGrafo ; TGrafo cria_grafo_por_nome ( char ∗ ) ; void i m p r i m i r _ s a l v a r ( Caminho ∗) ; 25 void i n i c i a _ m a t r i z ( TGrafo ∗) ; void i n s t _ m a t r i z ( TGrafo ∗, int ∗ int ∗ int ∗ , , ) ; 30 Caminho ∗ f l o y d P ( TGrafo ∗) ; void f l o y d ( TGrafo ∗, TVertice ∗∗ , int ∗ ∗ ) ; TVertice ∗∗ alocaMatriz ( TVertice ∗ ∗ int ∗ , ) ; 35 int ∗∗ iniciaPred ( int ∗∗ , int ∗ ) ; Caminho ∗ f l o y d P N e g ( TGrafo ∗ ) ; 40 void f l o y d N e g ( TGrafo ∗ TVertice ∗∗ , int ∗∗ ) ; Programa 15: TAD Grafo 2.4.1 Função CriaGrafoPorNome A Função 2.4.1 tem como objetivo fazer a leitura do grafo a partir de um arquivo .txt e ainda iniciar a matriz de adjacências 2.4.3 bem como instanciar a matriz com todos os pesos do grafo de um vértice A para um vértice B . E é claro, vericar para todos os vértices do grafo, durante a inserção, se o grafo contém aresta com peso negativo. Vide Programa 16 TGrafo cria_grafo_por_nome ( char ∗ nome ) { ∗ arqE ; char FILE ∗ buf , ∗ tok ; TGrafo g; 16
  • 21. 5 int char ∗ sizeof char numArestas , numVertices , vA , vB , peso , media_qtd_arestas ; ∗10) ; char ∗ sizeof char tok = ( ) malloc ( ( ) buf = ( ) malloc ( ( ) ∗100) ; r) ; if arqE = f o p e n ( nome , ( ! arqE ) { 10 printf ( Erro ao a b r i r o a r q u i v o de e n t r a d a %s , nome ) ; g . q t d V e r t = − 1; return (g) ; } while g . ehcicloNeg = 0; 15 ( ! f e o f ( arqE ) ) { if buf = f g e t s ( buf , BUFSIZ , arqE ) ; break ( buf == NULL) switch ; case ' p ' ( buf [ 0 ] ) { 20 : tok = ) ; s t r t o k ( buf , tok = s t r t o k (NULL, ) ; tok = s t r t o k (NULL, ) ; numVertices = a t o i ( tok ) ; 25 tok = s t r t o k (NULL, ) ; numArestas = a t o i ( tok ) ; g . qtdAres = numArestas ; g . qtdVert = numVertices ; break i n i c i a _ m a t r i z ( g ) ; 30 case ; 'a ' : tok = s t r t o k ( buf , ) ; tok = s t r t o k (NULL, ) ; vA = a t o i ( tok ) − 1; 35 tok = s t r t o k (NULL, ) ; vB = a t o i ( tok ) − 1; tok = s t r t o k (NULL, ) ; if peso = a t o i ( tok ) ; ( p e s o 0) 40 g . ehcicloNeg = 1; break g . m a t r i z [ vA ] [ vB ] . p e s o = peso ; default ; break : ; 45 } return } (g) ; } Programa 16: Função criagrafopornome 2.4.2 Função alocaMatriz Para a alocação da matriz, por padrão, seria feita em ordem de complexidade quadrática, no entanto, para otimizar o código zemos em ordem de complexidade linear. Para isso foi preciso alocar a matriz com a quantidade de linhas da matriz de adjacências e mais uma alocação para a posição matriz[0] com tamanho Linha ∗ Coluna, fazendo, em seguida, um redirecionamento dos endereços da matriz. Por exemplo, numa matriz 3x2 alocamos a matriz com 3 posições, sendo que para a matriz[0] alocaremos 6 posições. Assim, no redirecionamento dos ponteiros como, 17
  • 22. por exemplo, a posição matriz[1] receberá o endereço da matriz[0][i ∗ coluna], ou seja, matriz[0][1x2]. Para melhor entendimento, vide Figura 1 e Programa 17. Figura 1: Figura Repres. Alocação Matriz 18
  • 23. ∗∗ ∗∗ int ∗ int TVertice alocaMatriz ( TVertice matriz , tam ) { sizeof i , j ; ∗∗) ∗ tam ) ∗ ∗) ) ; if matriz = ( TVertice malloc (( ( TVertice ( matriz == NULL) { 5 Erro ao a l o c a r a m a t r i z n ) ; return printf ( 0; sizeof } matriz [ 0 ] = ( TVertice ∗) malloc ( ( ( ∗ tam ) ∗ ( ∗ tam ) ) ∗ ( TVertice ) ) if ; ( matriz [ 0 ] == NULL) { 10 Erro ao a l o c a r a m a t r i z n ) ; return printf ( 0; for } ( i = 1; i ( ∗ tam ) ; i ++) { matriz [ i ] = ( m a t r i z [ 0 ] [ i ∗ ( ∗ tam ) ] ) ; 15 return } matriz ; } Programa 17: Função alocaMatriz 2.4.3 Função iniciaMatriz Função responsável por alocar 2.4.2 e inicializar a matriz de adjacências. Vide Programa 18 void ∗ int i n i c i a _ m a t r i z ( TGrafo g) { i , j ; − −m a t r i z , (g−q t d V e r t ) ) ; for g m a t r i z = alocaMatriz (g −q t d V e r t ; i ++) for ( i = 0; i g 5 ( j = 0; j g− q t d V e r t ; j ++) −m a t r i z [ i ] [ j ] . p e s o = INF ; for g ( i = 0; i g− q t d V e r t ; i ++) g −m a t r i z [ i ] [ i ] . peso = 0; } Programa 18: Função iniciamatriz 2.4.4 Função iniciaPred Função semelhante a Função iniciaMatriz 2.4.3. Vide Programa 19 int ∗∗ int ∗∗ int ∗ int iniciaPred ( pred , tam ) { if i , j ; int ∗ ∗ sizeof int ∗ ( pred == NULL) { ∗ tam ) ∗ if pred = ( ) malloc (( ( )) ; 5 ( pred == NULL) { Erro ao a l o c a r a m a t r i z n ) ; return printf ( 0; int ∗ sizeof int } ∗ tam ) ∗ ( ∗ tam ) ) ∗ if pred [ 0 ] = ( ) malloc ( ( ( ( )) ; 10 ( pred [ 0 ] == NULL) { Erro ao a l o c a r a m a t r i z ) ; return printf ( 0; for } ( i = 1; i ( ∗ tam ) ; i ++) { 19
  • 24. 15 pred [ i ] = ( p r e d [ 0 ] [ ( ∗ tam ) ∗ i ]) ; } for } ∗ tam ) ; i ++) for ( i = 0; i ( ( j = 0; j ( ∗ tam ) ; j ++) 20 return pred [ i ] [ j ] = i ; pred ; } Programa 19: Função iniciaPred 2.5 Floyd-Warshall 2.5.1 Função oydP Função responsável por calcular a distância e predecessores de todos os vértices do grafo positivo, utilizando o Algoritmo de Floyd Warshall, note que não é preciso reinicializar a matriz de adjacências bem como a de predecessores uma vez que quando passarmos ao programa a ag 1 de impressão o programa executará somente uma única vez. Para uma ilustração da geração dos caminhos veja a Figura 5. Vide Programa 20 ∗ ∗ int Caminho f l o y d P ( TGrafo g) { k, i , j , aux , n = 0, pos ; ∗ int ∗∗ Caminho c ; pred ; 5 pred = NULL ; (g− sizeof pred = i n i c i a P r e d ( pred , q t d V e r t ) ) ; c = ( Caminho ∗) malloc (g −q t d V e r t ∗ ( Caminho ) ) ; c−n e g = 0; c−s = 0; 10 c− −q t d V e r t ; for t = g 0 ; k g− for (k = q t d V e r t ; k++) i g− for ( i = 0; q t d V e r t ; i ++) j g− if ( j = 0; q t d V e r t ; j ++) ( ( g− m a t r i z [ i ] [ k ] . p e s o + g−m a t r i z [ k ] [ j ] . peso ) − g matriz [ i ] [ j ] . peso ) { 15 g −m a t r i z [ i ] [ j ] . peso = g −m a t r i z [ i ] [ k ] . peso + g − matriz [ k ] [ j ] . peso ; pred [ i ] [ j ] = pred [ k ] [ j ] ; } −q t d T o t a l = g−q t d V e r t ; for c ( k = c− s ; k c− sizeof t ; k++) { 20 c [ k ] . resultado = ( TPasseio ∗) calloc (c −q t d T o t a l , ( for TPasseio ) ) ; −s ; −t ; int ∗ sizeof ( i = c i c i ++) { −q t d T o t a l int c [ k ] . r e s u l t a d o [ i ] . TP = ( ) calloc (c , ( if )) ; continue ( i == k) ; 25 c [ k ] . r e s u l t a d o [ i ] . TP [ 0 ] = g −m a t r i z [ k ] [ i ] . peso ; c [ k ] . r e s u l t a d o [ i ] . qtdNos = 1; pos = 1; while aux = pred [ k ] [ i ] ; ( ( aux != i ) ( aux != k) ) { 20
  • 25. 30 c [ k ] . r e s u l t a d o [ i ] . q t d N o s ++; c [ k ] . r e s u l t a d o [ i ] . TP [ p o s ++] = aux ; aux = p r e d [ k ] [ aux ] ; } } 35 } f r e e ( pred [ 0 ] ) ; return f r e e ( pred ) ; c ; } Programa 20: Função oydP 2.5.2 Função oyd Análogo a Função oydP 2.5.1, porém sem geração de caminhos e ainda dois pontos importantes: • Matriz de Distâncias: criamos uma matriz auxiliar que é alocada somente uma única vez e desalocada somente no nal das n execuções, porém sempre que é executada, inicializamos a matriz de modo que que de acordo com a especicação proposta pelo trabalho e ainda com código mais otimizado. • Matriz de Predecessores: Optamos por reutilizá-la, porém reiniciando-a na Função mainF 2.5.6 a cada execução. A função responsável por alocar e / ou inicialização do Pred pode ser conferida na Seção 2.4.4. Vale lembrar que a cada execução a matriz de predecessores é reinicializada, logo está de acordo com a especicação proposta pelo trabalho e ainda mais otimizado. void ∗ ∗∗ int ∗∗ int f l o y d ( TGrafo g , TVertice auxMatriz , pred ) { for k, i , j ; −q t d V e r t ; i ++) for ( i = 0; i g ( j = g− 0; jq t d V e r t ; j ++) 5 a u x M a t r i z [ i ] [ j ] = g− for m a t r i z [ i ] [ j ] ; = 0 ; k g− for (k q t d V e r t ; k++) { i g− for ( i = 0; q t d V e r t ; i ++) j g− if ( j = 0; q t d V e r t ; j ++) ( ( auxMatriz [ i ] [ k ] . peso + auxMatriz [ k ] [ j ] . peso ) auxMatriz [ i ] [ j ] . peso ) { 10 auxMatriz [ i ] [ j ] . peso = auxMatriz [ i ] [ k ] . peso + auxMatriz [ k ] [ j ] . peso ; pred [ i ] [ j ] = pred [ k ] [ j ] ; } } } Programa 21: Função oyd 2.5.3 Função oydPNeg Função responsável por calcular a distância e predecessores de todos os vértices do grafo negativo, utilizando o Algoritmo de Floyd Warshall, note que assim como o Programa20 não é preciso reinicializar a matriz de adjacências bem como a de 21
  • 26. predecessores uma vez que quando passarmos ao programa a ag 1 de impressão o programa executará somente uma única vez. Logo, bastará somente inicializá-la. Como o grafo é negativo (contém ciclos com pesos negativos), então será necessário sair da execução do algoritmo de Warshall e identicar o ciclo de peso negativo, gerando o caminho desse ciclo para futura impressão em arquivo. Isso é feito de modo análogo à geração de caminho da Seção 2.5.1, mas, para isso, bastará percor- rer e gerar o caminho da posição da matriz que foi identicado o ciclo negativo, ou seja, a posição de uma das diagonais principais da matriz de adjacências do grafo. Obs.: Para contornar a condição de parada do programa para ciclos negativos, incrementamos uma unidade na quantidade da posição em que a matriz sua diagonal principal foi modicada, isso somente para a representação do vértice nal. Para uma ilustração da geração dos caminhos veja a Figura 14. Vide Programa 22 ∗ ∗ int Caminho f l o y d P N e g ( TGrafo g) { k, i , j , aux , n = 0, pos ; ∗ int ∗∗ Caminho c ; pred ; 5 pred = NULL ; (g− sizeof pred = i n i c i a P r e d ( pred , q t d V e r t ) ) ; c = ( Caminho ∗) malloc (g −q t d V e r t ∗ ( Caminho ) ) ; c−n e g = 0; c−s = 0; 10 c− −q t d V e r t ; for t = g 0 ; k g− for (k = q t d V e r t ; k++) { i g− for ( i = 0; q t d V e r t ; i ++) j g− if ( j = 0; q t d V e r t ; j ++) { ( ( g− m a t r i z [ i ] [ k ] . p e s o + g− m a t r i z [ k ] [ j ] . peso ) − g matriz [ i ] [ j ] . peso ) { 15 g−m a t r i z [ i ] [ j ] . peso = g −m a t r i z [ i ] [ k ] . peso + g − matriz [ k ] [ j ] . peso ; if pred [ i ] [ j ] = pred [ k ] [ j ] ; (g −m a t r i z [ i ] [ i ] . peso 0) { c−n e g = 1 ; c−s = i ; 20 c− goto t = i + 1 ; NEG ; } } } 25 } NEG : −q t d T o t a l = g−q t d V e r t ; for c ( k = c− s ; k c− sizeof t ; k++) { c [ k ] . resultado = ( TPasseio ∗) calloc (c −q t d T o t a l , ( for TPasseio ) ) ; 30 −s ; −t ; int ∗ sizeof ( i = c i c i ++) { −q t d T o t a l int c [ k ] . r e s u l t a d o [ i ] . TP = ( ) calloc (c , ( )) ; c [ k ] . r e s u l t a d o [ i ] . TP [ 0 ] = g −m a t r i z [ k ] [ i ] . peso ; c [ k ] . r e s u l t a d o [ i ] . qtdNos = 1; pos = 1; 35 while aux = pred [ k ] [ i ] ; ( ( aux != i ) ( aux != k) ) { c [ k ] . r e s u l t a d o [ i ] . q t d N o s ++; c [ k ] . r e s u l t a d o [ i ] . TP [ p o s ++] = aux ; 22
  • 27. aux = p r e d [ k ] [ aux ] ; 40 } } } f r e e ( pred [ 0 ] ) ; return f r e e ( pred ) ; 45 c ; } Programa 22: Função oydPNeg 2.5.4 Função oydNeg Análogo a Função oydPNeg 2.5.3, porém sem geração de caminhos e ainda com o mesmo ponto importante da Seção 2.5.2. void ∗ ∗∗ int ∗∗ int f l o y d N e g ( TGrafo g , TVertice auxMatriz , pred ) { for k, i , j ; −q t d V e r t ; i ++) for ( i = 0; i g ( j = g− 0; j q t d V e r t ; j ++) 5 a u x M a t r i z [ i ] [ j ] = g− for m a t r i z [ i ] [ j ] ; = 0 ; k g− for (k q t d V e r t ; k++) i g− for ( i = 0; q t d V e r t ; i ++) j g− if ( j = 0; q t d V e r t ; j ++) ( ( auxMatriz [ i ] [ k ] . peso + auxMatriz [ k ] [ j ] . peso ) auxMatriz [ i ] [ j ] . peso ) { 10 auxMatriz [ i ] [ j ] . peso = auxMatriz [ i ] [ k ] . peso + auxMatriz [ k ] [ j ] . peso ; if pred [ i ] [ j ] = pred [ k ] [ j ] ; return ( auxMatriz [ i ] [ i ] . peso 0) { ; } 15 } } Programa 23: Função oydNeg 2.5.5 Função imprimirsalvar Função utilizada para impressão dos resultados, isto é, distância e peso de todos os vértices para os demais vértices do grafo bem como o caminho entres os vértices de início e nal. Obs.: Como os caminhos de cada vértice são acessados e armazenados em ordem inversa a impressão dos caminhos é feita em ordem inversa para que os caminhos de saída estejam na ordem correta. Um exemplo dessa geração de caminhos pode ser vista na Figura 5. Vide Programa 24 void i m p r i m i r _ s a l v a r ( Caminho ∗ c) { ∗ int FILE arqS ; i , j , k; s p a t h s . t x t , w ) ; if arqS = fopen ( 5 ( ! arqS ) { Erro ao e s c r e v e r no a r q u i v o ) ; return printf ( ; if } (c −n e g ) 23