O Algoritmo de Bellman-Ford é um algoritmo de busca de caminho mínimo em um digrafo (grafo orientado ou dirigido) ponderado, ou seja, cujas arestas têm peso, inclusive negativo. O Algoritmo de Dijkstra resolve o mesmo problema, num tempo menor, porém exige que todas as arestas tenham pesos positivos. Portanto, o algoritmo de Bellman-Ford é normalmente usado apenas quando existem arestas de peso negativo.[1]

O algoritmo de Bellman-Ford executa em tempo onde V é o número de vértices e E o número de arestas.[2][3]

Pseudocódigo

editar

Assim como o algoritmo de Dijkstra, o algoritmo de Bellman-Ford utiliza a técnica de relaxamento, ou seja, realiza sucessivas aproximações das distâncias até finalmente chegar na solução. A principal diferença entre Dijkstra e Bellman-Ford é que no algoritmo de Dijkstra é utilizada uma fila de prioridades para selecionar os vértices a serem relaxados, enquanto o algoritmo de Bellman-Ford simplesmente relaxa todas as arestas.

Bellman_Ford(G,pesos,inicial)
    para todo vertice ∈ V
        λ[vertice] ← ∞
        π[vertice] ← nulo

    λ[inicial] ← 0

    para i de 1 até |V| -1
        para toda aresta = (u,v) ∈ A
            se λ[v] > λ[u] + pesos(u,v) # relaxamento
               λ[v] ← λ[u] + pesos(u,v)
               π[v] ← u

G é um grafo no formato G = (V,A), π[v] indica o predecessor de v, λ[v] é o custo de sair da origem e chegar até o vértice v e inicial é o vértice inicial. Após o término do algoritmo, para cada v pertencente aos vértices de G, π[v] → y representa uma aresta selecionada para a árvore geradora mínima (se y ≠ nulo) e, pensando em árvore, λ[v] representa a distância da raiz até o vértice v.

Exemplo de código

editar

C++

editar
#include <iostream>

#include <vector>

#include <array>

#include <climits> // INT_MAX



using namespace std;



struct Node {

  int p = -1;

  int d = INT_MAX;

};



using edges_t = vector<array<int, 2>>;

using graph_t = vector<edges_t>;



// if a function of this type returns true, graph traversal will be interrupted

using edge_cb = bool(*)(vector<Node>&, int, int, int);



inline bool isNegativeCycle(vector<Node>& nodes, int u, int v, int w) {

  return nodes[v].d > nodes[u].d + w;

}



inline bool relaxNode(vector<Node>& nodes, int u, int v, int w) {

  // Relaxation

  if (nodes[v].d > nodes[u].d + w) {

    nodes[v].d = nodes[u].d + w;

    nodes[v].p = u;

  }



  return false;

}



// returns true if the traversal was successful

bool traverseAllEdges(const graph_t& graph, vector<Node>& nodes, edge_cb cb) {

  for (int u = 0; u < graph.size(); ++u) {

    const edges_t adjacent = graph[u];



    for (const auto& edge : adjacent) {

      int v = edge[0]; // Adjacent vertex

      int w = edge[1]; // Weight

  

      if (cb(nodes, u, v, w)) return false;

    }

  }



  return true;

}



bool bellmanFord(const graph_t& graph, int src, int dst, vector<int>& path) {

  const int len = graph.size();

  vector<Node> nodes(len);

  

  // Initialization

  for (int i = 0; i < len; ++i) {

    nodes[i] = Node();

  }

  

  nodes[src].d = 0;



  for (int i = 0; i < len; ++i) {

    traverseAllEdges(graph, nodes, relaxNode);

  }



  // Check for negative-weight cycles

  // Stop, if such cycles were detected

  if (!traverseAllEdges(graph, nodes, isNegativeCycle)) return false;



  // Construct the path from src to dst

  path.push_back(dst);



  Node node = nodes[dst];



  while (node.p != -1) {

    path.insert(path.begin(), node.p);

    node = nodes[node.p];

  } 



  return true;

}



int main() {

  graph_t graph(5, edges_t(3));



  graph[0] = {{1, 6}, {3, 7}};

  graph[1] = {{2, 5}, {3, 8}, {4, -4}};

  graph[2] = {{1, -2}};

  graph[3] = {{2, -3}, {4, 9}};

  graph[4] = {{0, 2}, {2, 7}};



  vector<int> path;



  if (bellmanFord(graph, 0, 2, path)) {

    for (const int& v : path) {

      cout << v << ' ';

    }

  } else {

      cout << "negative cycle detected\n";

  }

}

[4]

Ver também

editar

Referências

  1. Thomas H. Cormen, Charles Leiserson, Ronald L. Rivest, Clifford Stein (2007). Algorithmen – Eine Einführung 2. ed. München: Oldenbourg Wissenschaftsverlag. pp. 585–586. ISBN 978-3-486-58262-8 
  2. RFC 1058
  3. [1]
  4. https://gist.github.com/alexnoz/3f96d821481b2879ba7b683501d2d8d1

Ligações externas

editar
Ícone de esboço Este artigo sobre programação de computadores é um esboço. Você pode ajudar a Wikipédia expandindo-o.

📚 Artikel Terkait di Wikipedia

Psiquiatria

2026  «Changes of Functional Brain Networks in Major Depressive Disorder: A Graph Theoretical Analysis of Resting-State fMRI». PLOS One. Consultado em 10

Busca em profundidade

(2011), Graph Algorithms, ISBN 978-0-521-73653-4 2nd ed. , Cambridge University Press, pp. 46–48 . Sedgewick, Robert (2002), Algorithms in C++: Graph Algorithms

Função quadrática

{b^{2}}{4a}}\right).} Predefinição:Quadratic equation graph key points.svgPredefinição:Quadratic function graph complex roots.svg As raízes (ou zeros ), r1 e

Função digama

Stegun, I. A. (Eds.). "Psi (Digamma) Function." §6.3 in Handbook of Mathematical Functions with Formulas, Graphs, and Mathematical Tables, 9th printing

Toshikazu Sunada

Pavel Exner, Jonathan Keating, Alexander Teplyaev (Eds.): Analysis on Graphs and its applications, American Mathematical Society 2008, Proc. Symp. Pure

Grafos aleatórios exponenciais

exponential random graph models». Social Networks. 33: 41–55. doi:10.1016/j.socnet.2010.09.004  Erdős, P.; Rényi, A (1959). «On random graphs». Publicationes

Plástico

2006). «The estrogenic effect of bisphenol A disrupts pancreatic beta-cell function in vivo and induces insulin resistance». Environmental Health Perspectives

Hipótese de Riemann

original em 4 de janeiro de 2009  de Vries, Andreas (2004), The Graph of the Riemann Zeta function ζ(s) , a simple animated Java applet. Watkins, Matthew R.