检测图中的负循环 | (贝尔曼福特)
我们得到一个有向图。我们需要计算图是否有负循环。负循环是循环的总和变为负的循环。
在图形的各种应用中都可以找到负权重。例如,如果我们遵循路径,我们可能会获得一些优势,而不是为路径支付成本。
例子:
Input : 4 4
0 1 1
1 2 -1
2 3 -1
3 0 -1
Output : Yes
The graph contains a negative cycle.
推荐:请先在“PRACTICE”上解决,然后再继续解决。
这个想法是使用贝尔曼-福特算法。
下面是一种算法,用于查找是否存在可从给定源获得的负权重循环。
1)初始化从源到所有顶点的距离为无穷大,到源本身的距离为 0。创建一个大小为 |V| 的数组 dist[]所有值都是无限的,除了 dist[src] ,其中 src 是源顶点。
2)这一步计算最短距离。执行以下 |V|-1 次,其中 |V|是给定图中的顶点数。
a)对每个边 uv 执行以下操作。
b)如果 dist[v] > dist[u] + 边 uv 的权重,则更新 dist[v]。
c) dist[v] = dist[u] + 边 uv 的权重。
3)此步骤报告图表中是否存在负权重循环。对每个边缘 uv 执行以下操作
a)如果 dist[v] > dist[u] + 边 uv 的权重,则“图有负权重循环”
第 3 步的想法是,如果图不包含负权重循环,第 2 步保证最短距离。如果我们再次遍历所有边并为任何顶点获得更短的路径,则存在负权重循环。
C++
// A C++ program to check if a graph contains negative
// weight cycle using Bellman-Ford algorithm. This program
// works only if all vertices are reachable from a source
// vertex 0.
#include
using namespace std;
// a structure to represent a weighted edge in graph
struct Edge {
int src, dest, weight;
};
// a structure to represent a connected, directed and
// weighted graph
struct Graph {
// V-> Number of vertices, E-> Number of edges
int V, E;
// graph is represented as an array of edges.
struct Edge* edge;
};
// Creates a graph with V vertices and E edges
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = new Graph;
graph->V = V;
graph->E = E;
graph->edge = new Edge[graph->E];
return graph;
}
// The main function that finds shortest distances
// from src to all other vertices using Bellman-
// Ford algorithm. The function also detects
// negative weight cycle
bool isNegCycleBellmanFord(struct Graph* graph,
int src)
{
int V = graph->V;
int E = graph->E;
int dist[V];
// Step 1: Initialize distances from src
// to all other vertices as INFINITE
for (int i = 0; i < V; i++)
dist[i] = INT_MAX;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times.
// A simple shortest path from src to any
// other vertex can have at-most |V| - 1
// edges
for (int i = 1; i <= V - 1; i++) {
for (int j = 0; j < E; j++) {
int u = graph->edge[j].src;
int v = graph->edge[j].dest;
int weight = graph->edge[j].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
// Step 3: check for negative-weight cycles.
// The above step guarantees shortest distances
// if graph doesn't contain negative weight cycle.
// If we get a shorter path, then there
// is a cycle.
for (int i = 0; i < E; i++) {
int u = graph->edge[i].src;
int v = graph->edge[i].dest;
int weight = graph->edge[i].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
return true;
}
return false;
}
// Driver program to test above functions
int main()
{
/* Let us create the graph given in above example */
int V = 5; // Number of vertices in graph
int E = 8; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
// add edge 0-1 (or A-B in above figure)
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[0].weight = -1;
// add edge 0-2 (or A-C in above figure)
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 4;
// add edge 1-2 (or B-C in above figure)
graph->edge[2].src = 1;
graph->edge[2].dest = 2;
graph->edge[2].weight = 3;
// add edge 1-3 (or B-D in above figure)
graph->edge[3].src = 1;
graph->edge[3].dest = 3;
graph->edge[3].weight = 2;
// add edge 1-4 (or A-E in above figure)
graph->edge[4].src = 1;
graph->edge[4].dest = 4;
graph->edge[4].weight = 2;
// add edge 3-2 (or D-C in above figure)
graph->edge[5].src = 3;
graph->edge[5].dest = 2;
graph->edge[5].weight = 5;
// add edge 3-1 (or D-B in above figure)
graph->edge[6].src = 3;
graph->edge[6].dest = 1;
graph->edge[6].weight = 1;
// add edge 4-3 (or E-D in above figure)
graph->edge[7].src = 4;
graph->edge[7].dest = 3;
graph->edge[7].weight = -3;
if (isNegCycleBellmanFord(graph, 0))
cout << "Yes";
else
cout << "No";
return 0;
}
Java
// Java program to check if a graph contains negative
// weight cycle using Bellman-Ford algorithm. This program
// works only if all vertices are reachable from a source
// vertex 0.
import java.util.*;
class GFG {
// a structure to represent a weighted edge in graph
static class Edge {
int src, dest, weight;
}
// a structure to represent a connected, directed and
// weighted graph
static class Graph {
// V-> Number of vertices, E-> Number of edges
int V, E;
// graph is represented as an array of edges.
Edge edge[];
}
// Creates a graph with V vertices and E edges
static Graph createGraph(int V, int E) {
Graph graph = new Graph();
graph.V = V;
graph.E = E;
graph.edge = new Edge[graph.E];
for (int i = 0; i < graph.E; i++) {
graph.edge[i] = new Edge();
}
return graph;
}
// The main function that finds shortest distances
// from src to all other vertices using Bellman-
// Ford algorithm. The function also detects
// negative weight cycle
static boolean isNegCycleBellmanFord(Graph graph, int src) {
int V = graph.V;
int E = graph.E;
int[] dist = new int[V];
// Step 1: Initialize distances from src
// to all other vertices as INFINITE
for (int i = 0; i < V; i++)
dist[i] = Integer.MAX_VALUE;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times.
// A simple shortest path from src to any
// other vertex can have at-most |V| - 1
// edges
for (int i = 1; i <= V - 1; i++) {
for (int j = 0; j < E; j++) {
int u = graph.edge[j].src;
int v = graph.edge[j].dest;
int weight = graph.edge[j].weight;
if (dist[u] != Integer.MAX_VALUE && dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
// Step 3: check for negative-weight cycles.
// The above step guarantees shortest distances
// if graph doesn't contain negative weight cycle.
// If we get a shorter path, then there
// is a cycle.
for (int i = 0; i < E; i++) {
int u = graph.edge[i].src;
int v = graph.edge[i].dest;
int weight = graph.edge[i].weight;
if (dist[u] != Integer.MAX_VALUE && dist[u] + weight < dist[v])
return true;
}
return false;
}
// Driver Code
public static void main(String[] args) {
int V = 5, E = 8;
Graph graph = createGraph(V, E);
// add edge 0-1 (or A-B in above figure)
graph.edge[0].src = 0;
graph.edge[0].dest = 1;
graph.edge[0].weight = -1;
// add edge 0-2 (or A-C in above figure)
graph.edge[1].src = 0;
graph.edge[1].dest = 2;
graph.edge[1].weight = 4;
// add edge 1-2 (or B-C in above figure)
graph.edge[2].src = 1;
graph.edge[2].dest = 2;
graph.edge[2].weight = 3;
// add edge 1-3 (or B-D in above figure)
graph.edge[3].src = 1;
graph.edge[3].dest = 3;
graph.edge[3].weight = 2;
// add edge 1-4 (or A-E in above figure)
graph.edge[4].src = 1;
graph.edge[4].dest = 4;
graph.edge[4].weight = 2;
// add edge 3-2 (or D-C in above figure)
graph.edge[5].src = 3;
graph.edge[5].dest = 2;
graph.edge[5].weight = 5;
// add edge 3-1 (or D-B in above figure)
graph.edge[6].src = 3;
graph.edge[6].dest = 1;
graph.edge[6].weight = 1;
// add edge 4-3 (or E-D in above figure)
graph.edge[7].src = 4;
graph.edge[7].dest = 3;
graph.edge[7].weight = -3;
if (isNegCycleBellmanFord(graph, 0))
System.out.println("Yes");
else
System.out.println("No");
}
}
// This code is contributed by
// sanjeev2552
Python3
# A Python3 program to check if a graph contains negative
# weight cycle using Bellman-Ford algorithm. This program
# works only if all vertices are reachable from a source
# vertex 0.
# a structure to represent a weighted edge in graph
class Edge:
def __init__(self):
self.src = 0
self.dest = 0
self.weight = 0
# a structure to represent a connected, directed and
# weighted graph
class Graph:
def __init__(self):
# V. Number of vertices, E. Number of edges
self.V = 0
self.E = 0
# graph is represented as an array of edges.
self.edge = None
# Creates a graph with V vertices and E edges
def createGraph(V, E):
graph = Graph()
graph.V = V;
graph.E = E;
graph.edge =[Edge() for i in range(graph.E)]
return graph;
# The main function that finds shortest distances
# from src to all other vertices using Bellman-
# Ford algorithm. The function also detects
# negative weight cycle
def isNegCycleBellmanFord(graph, src):
V = graph.V;
E = graph.E;
dist = [1000000 for i in range(V)];
dist[src] = 0;
# Step 2: Relax all edges |V| - 1 times.
# A simple shortest path from src to any
# other vertex can have at-most |V| - 1
# edges
for i in range(1, V):
for j in range(E):
u = graph.edge[j].src;
v = graph.edge[j].dest;
weight = graph.edge[j].weight;
if (dist[u] != 1000000 and dist[u] + weight < dist[v]):
dist[v] = dist[u] + weight;
# Step 3: check for negative-weight cycles.
# The above step guarantees shortest distances
# if graph doesn't contain negative weight cycle.
# If we get a shorter path, then there
# is a cycle.
for i in range(E):
u = graph.edge[i].src;
v = graph.edge[i].dest;
weight = graph.edge[i].weight;
if (dist[u] != 1000000 and dist[u] + weight < dist[v]):
return True;
return False;
# Driver program to test above functions
if __name__=='__main__':
# Let us create the graph given in above example
V = 5; # Number of vertices in graph
E = 8; # Number of edges in graph
graph = createGraph(V, E);
# add edge 0-1 (or A-B in above figure)
graph.edge[0].src = 0;
graph.edge[0].dest = 1;
graph.edge[0].weight = -1;
# add edge 0-2 (or A-C in above figure)
graph.edge[1].src = 0;
graph.edge[1].dest = 2;
graph.edge[1].weight = 4;
# add edge 1-2 (or B-C in above figure)
graph.edge[2].src = 1;
graph.edge[2].dest = 2;
graph.edge[2].weight = 3;
# add edge 1-3 (or B-D in above figure)
graph.edge[3].src = 1;
graph.edge[3].dest = 3;
graph.edge[3].weight = 2;
# add edge 1-4 (or A-E in above figure)
graph.edge[4].src = 1;
graph.edge[4].dest = 4;
graph.edge[4].weight = 2;
# add edge 3-2 (or D-C in above figure)
graph.edge[5].src = 3;
graph.edge[5].dest = 2;
graph.edge[5].weight = 5;
# add edge 3-1 (or D-B in above figure)
graph.edge[6].src = 3;
graph.edge[6].dest = 1;
graph.edge[6].weight = 1;
# add edge 4-3 (or E-D in above figure)
graph.edge[7].src = 4;
graph.edge[7].dest = 3;
graph.edge[7].weight = -3;
if (isNegCycleBellmanFord(graph, 0)):
print("Yes")
else:
print("No")
# This code is contributed by pratham76
C#
// C# program to check if a graph contains negative
// weight cycle using Bellman-Ford algorithm. This program
// works only if all vertices are reachable from a source
// vertex 0.
using System;
using System.Collections;
using System.Collections.Generic;
class GFG {
// a structure to represent a weighted edge in graph
class Edge {
public int src, dest, weight;
}
// a structure to represent a connected, directed and
// weighted graph
class Graph {
// V-> Number of vertices, E-> Number of edges
public int V, E;
// graph is represented as an array of edges.
public Edge []edge;
}
// Creates a graph with V vertices and E edges
static Graph createGraph(int V, int E) {
Graph graph = new Graph();
graph.V = V;
graph.E = E;
graph.edge = new Edge[graph.E];
for (int i = 0; i < graph.E; i++) {
graph.edge[i] = new Edge();
}
return graph;
}
// The main function that finds shortest distances
// from src to all other vertices using Bellman-
// Ford algorithm. The function also detects
// negative weight cycle
static bool isNegCycleBellmanFord(Graph graph, int src) {
int V = graph.V;
int E = graph.E;
int[] dist = new int[V];
// Step 1: Initialize distances from src
// to all other vertices as INFINITE
for (int i = 0; i < V; i++)
dist[i] = 1000000;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times.
// A simple shortest path from src to any
// other vertex can have at-most |V| - 1
// edges
for (int i = 1; i <= V - 1; i++) {
for (int j = 0; j < E; j++) {
int u = graph.edge[j].src;
int v = graph.edge[j].dest;
int weight = graph.edge[j].weight;
if (dist[u] != 1000000 && dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
// Step 3: check for negative-weight cycles.
// The above step guarantees shortest distances
// if graph doesn't contain negative weight cycle.
// If we get a shorter path, then there
// is a cycle.
for (int i = 0; i < E; i++) {
int u = graph.edge[i].src;
int v = graph.edge[i].dest;
int weight = graph.edge[i].weight;
if (dist[u] != 1000000 && dist[u] + weight < dist[v])
return true;
}
return false;
}
// Driver Code
public static void Main(string[] args) {
int V = 5, E = 8;
Graph graph = createGraph(V, E);
// add edge 0-1 (or A-B in above figure)
graph.edge[0].src = 0;
graph.edge[0].dest = 1;
graph.edge[0].weight = -1;
// add edge 0-2 (or A-C in above figure)
graph.edge[1].src = 0;
graph.edge[1].dest = 2;
graph.edge[1].weight = 4;
// add edge 1-2 (or B-C in above figure)
graph.edge[2].src = 1;
graph.edge[2].dest = 2;
graph.edge[2].weight = 3;
// add edge 1-3 (or B-D in above figure)
graph.edge[3].src = 1;
graph.edge[3].dest = 3;
graph.edge[3].weight = 2;
// add edge 1-4 (or A-E in above figure)
graph.edge[4].src = 1;
graph.edge[4].dest = 4;
graph.edge[4].weight = 2;
// add edge 3-2 (or D-C in above figure)
graph.edge[5].src = 3;
graph.edge[5].dest = 2;
graph.edge[5].weight = 5;
// add edge 3-1 (or D-B in above figure)
graph.edge[6].src = 3;
graph.edge[6].dest = 1;
graph.edge[6].weight = 1;
// add edge 4-3 (or E-D in above figure)
graph.edge[7].src = 4;
graph.edge[7].dest = 3;
graph.edge[7].weight = -3;
if (isNegCycleBellmanFord(graph, 0))
Console.Write("Yes");
else
Console.Write("No");
}
}
// This code is contributed by rutvik_56
Javascript
C++
// A C++ program for Bellman-Ford's single source
// shortest path algorithm.
#include
using namespace std;
// a structure to represent a weighted edge in graph
struct Edge {
int src, dest, weight;
};
// a structure to represent a connected, directed and
// weighted graph
struct Graph {
// V-> Number of vertices, E-> Number of edges
int V, E;
// graph is represented as an array of edges.
struct Edge* edge;
};
// Creates a graph with V vertices and E edges
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = new Graph;
graph->V = V;
graph->E = E;
graph->edge = new Edge[graph->E];
return graph;
}
// The main function that finds shortest distances
// from src to all other vertices using Bellman-
// Ford algorithm. The function also detects
// negative weight cycle
bool isNegCycleBellmanFord(struct Graph* graph,
int src, int dist[])
{
int V = graph->V;
int E = graph->E;
// Step 1: Initialize distances from src
// to all other vertices as INFINITE
for (int i = 0; i < V; i++)
dist[i] = INT_MAX;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times.
// A simple shortest path from src to any
// other vertex can have at-most |V| - 1
// edges
for (int i = 1; i <= V - 1; i++) {
for (int j = 0; j < E; j++) {
int u = graph->edge[j].src;
int v = graph->edge[j].dest;
int weight = graph->edge[j].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
// Step 3: check for negative-weight cycles.
// The above step guarantees shortest distances
// if graph doesn't contain negative weight cycle.
// If we get a shorter path, then there
// is a cycle.
for (int i = 0; i < E; i++) {
int u = graph->edge[i].src;
int v = graph->edge[i].dest;
int weight = graph->edge[i].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
return true;
}
return false;
}
// Returns true if given graph has negative weight
// cycle.
bool isNegCycleDisconnected(struct Graph* graph)
{
int V = graph->V;
// To keep track of visited vertices to avoid
// recomputations.
bool visited[V];
memset(visited, 0, sizeof(visited));
// This array is filled by Bellman-Ford
int dist[V];
// Call Bellman-Ford for all those vertices
// that are not visited
for (int i = 0; i < V; i++) {
if (visited[i] == false) {
// If cycle found
if (isNegCycleBellmanFord(graph, i, dist))
return true;
// Mark all vertices that are visited
// in above call.
for (int i = 0; i < V; i++)
if (dist[i] != INT_MAX)
visited[i] = true;
}
}
return false;
}
// Driver program to test above functions
int main()
{
/* Let us create the graph given in above example */
int V = 5; // Number of vertices in graph
int E = 8; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
// add edge 0-1 (or A-B in above figure)
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[0].weight = -1;
// add edge 0-2 (or A-C in above figure)
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 4;
// add edge 1-2 (or B-C in above figure)
graph->edge[2].src = 1;
graph->edge[2].dest = 2;
graph->edge[2].weight = 3;
// add edge 1-3 (or B-D in above figure)
graph->edge[3].src = 1;
graph->edge[3].dest = 3;
graph->edge[3].weight = 2;
// add edge 1-4 (or A-E in above figure)
graph->edge[4].src = 1;
graph->edge[4].dest = 4;
graph->edge[4].weight = 2;
// add edge 3-2 (or D-C in above figure)
graph->edge[5].src = 3;
graph->edge[5].dest = 2;
graph->edge[5].weight = 5;
// add edge 3-1 (or D-B in above figure)
graph->edge[6].src = 3;
graph->edge[6].dest = 1;
graph->edge[6].weight = 1;
// add edge 4-3 (or E-D in above figure)
graph->edge[7].src = 4;
graph->edge[7].dest = 3;
graph->edge[7].weight = -3;
if (isNegCycleDisconnected(graph))
cout << "Yes";
else
cout << "No";
return 0;
}
Java
// A Java program for Bellman-Ford's single source
// shortest path algorithm.
import java.util.*;
class GFG{
// A structure to represent a weighted
// edge in graph
static class Edge
{
int src, dest, weight;
}
// A structure to represent a connected,
// directed and weighted graph
static class Graph
{
// V-> Number of vertices,
// E-> Number of edges
int V, E;
// Graph is represented as
// an array of edges.
Edge edge[];
}
// Creates a graph with V vertices and E edges
static Graph createGraph(int V, int E)
{
Graph graph = new Graph();
graph.V = V;
graph.E = E;
graph.edge = new Edge[graph.E];
for(int i = 0; i < graph.E; i++)
{
graph.edge[i] = new Edge();
}
return graph;
}
// The main function that finds shortest distances
// from src to all other vertices using Bellman-
// Ford algorithm. The function also detects
// negative weight cycle
static boolean isNegCycleBellmanFord(Graph graph,
int src,
int dist[])
{
int V = graph.V;
int E = graph.E;
// Step 1: Initialize distances from src
// to all other vertices as INFINITE
for(int i = 0; i < V; i++)
dist[i] = Integer.MAX_VALUE;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times.
// A simple shortest path from src to any
// other vertex can have at-most |V| - 1
// edges
for(int i = 1; i <= V - 1; i++)
{
for(int j = 0; j < E; j++)
{
int u = graph.edge[j].src;
int v = graph.edge[j].dest;
int weight = graph.edge[j].weight;
if (dist[u] != Integer.MAX_VALUE &&
dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
// Step 3: check for negative-weight cycles.
// The above step guarantees shortest distances
// if graph doesn't contain negative weight cycle.
// If we get a shorter path, then there
// is a cycle.
for(int i = 0; i < E; i++)
{
int u = graph.edge[i].src;
int v = graph.edge[i].dest;
int weight = graph.edge[i].weight;
if (dist[u] != Integer.MAX_VALUE &&
dist[u] + weight < dist[v])
return true;
}
return false;
}
// Returns true if given graph has negative weight
// cycle.
static boolean isNegCycleDisconnected(Graph graph)
{
int V = graph.V;
// To keep track of visited vertices
// to avoid recomputations.
boolean visited[] = new boolean[V];
Arrays.fill(visited, false);
// This array is filled by Bellman-Ford
int dist[] = new int[V];
// Call Bellman-Ford for all those vertices
// that are not visited
for(int i = 0; i < V; i++)
{
if (visited[i] == false)
{
// If cycle found
if (isNegCycleBellmanFord(graph, i, dist))
return true;
// Mark all vertices that are visited
// in above call.
for(int j = 0; j < V; j++)
if (dist[j] != Integer.MAX_VALUE)
visited[j] = true;
}
}
return false;
}
// Driver Code
public static void main(String[] args)
{
int V = 5, E = 8;
Graph graph = createGraph(V, E);
// Add edge 0-1 (or A-B in above figure)
graph.edge[0].src = 0;
graph.edge[0].dest = 1;
graph.edge[0].weight = -1;
// Add edge 0-2 (or A-C in above figure)
graph.edge[1].src = 0;
graph.edge[1].dest = 2;
graph.edge[1].weight = 4;
// Add edge 1-2 (or B-C in above figure)
graph.edge[2].src = 1;
graph.edge[2].dest = 2;
graph.edge[2].weight = 3;
// Add edge 1-3 (or B-D in above figure)
graph.edge[3].src = 1;
graph.edge[3].dest = 3;
graph.edge[3].weight = 2;
// Add edge 1-4 (or A-E in above figure)
graph.edge[4].src = 1;
graph.edge[4].dest = 4;
graph.edge[4].weight = 2;
// Add edge 3-2 (or D-C in above figure)
graph.edge[5].src = 3;
graph.edge[5].dest = 2;
graph.edge[5].weight = 5;
// Add edge 3-1 (or D-B in above figure)
graph.edge[6].src = 3;
graph.edge[6].dest = 1;
graph.edge[6].weight = 1;
// Add edge 4-3 (or E-D in above figure)
graph.edge[7].src = 4;
graph.edge[7].dest = 3;
graph.edge[7].weight = -3;
if (isNegCycleDisconnected(graph))
System.out.println("Yes");
else
System.out.println("No");
}
}
// This code is contributed by adityapande88
Python3
# A Python3 program for Bellman-Ford's single source
# shortest path algorithm.
# The main function that finds shortest distances
# from src to all other vertices using Bellman-
# Ford algorithm. The function also detects
# negative weight cycle
def isNegCycleBellmanFord(src, dist):
global graph, V, E
# Step 1: Initialize distances from src
# to all other vertices as INFINITE
for i in range(V):
dist[i] = 10**18
dist[src] = 0
# Step 2: Relax all edges |V| - 1 times.
# A simple shortest path from src to any
# other vertex can have at-most |V| - 1
# edges
for i in range(1,V):
for j in range(E):
u = graph[j][0]
v = graph[j][1]
weight = graph[j][2]
if (dist[u] != 10**18 and dist[u] + weight < dist[v]):
dist[v] = dist[u] + weight
# Step 3: check for negative-weight cycles.
# The above step guarantees shortest distances
# if graph doesn't contain negative weight cycle.
# If we get a shorter path, then there
# is a cycle.
for i in range(E):
u = graph[i][0]
v = graph[i][1]
weight = graph[i][2]
if (dist[u] != 10**18 and dist[u] + weight < dist[v]):
return True
return False
# Returns true if given graph has negative weight
# cycle.
def isNegCycleDisconnected():
global V, E, graph
# To keep track of visited vertices to avoid
# recomputations.
visited = [0]*V
# memset(visited, 0, sizeof(visited))
# This array is filled by Bellman-Ford
dist = [0]*V
# Call Bellman-Ford for all those vertices
# that are not visited
for i in range(V):
if (visited[i] == 0):
# If cycle found
if (isNegCycleBellmanFord(i, dist)):
return True
# Mark all vertices that are visited
# in above call.
for i in range(V):
if (dist[i] != 10**18):
visited[i] = True
return False
# Driver code
if __name__ == '__main__':
# /* Let us create the graph given in above example */
V = 5 # Number of vertices in graph
E = 8 # Number of edges in graph
graph = [[0, 0, 0] for i in range(8)]
# add edge 0-1 (or A-B in above figure)
graph[0][0] = 0
graph[0][1] = 1
graph[0][2] = -1
# add edge 0-2 (or A-C in above figure)
graph[1][0] = 0
graph[1][1] = 2
graph[1][2] = 4
# add edge 1-2 (or B-C in above figure)
graph[2][0] = 1
graph[2][1] = 2
graph[2][2] = 3
# add edge 1-3 (or B-D in above figure)
graph[3][0] = 1
graph[3][1] = 3
graph[3][2] = 2
# add edge 1-4 (or A-E in above figure)
graph[4][0] = 1
graph[4][1] = 4
graph[4][2] = 2
# add edge 3-2 (or D-C in above figure)
graph[5][0] = 3
graph[5][1] = 2
graph[5][2] = 5
# add edge 3-1 (or D-B in above figure)
graph[6][0] = 3
graph[6][1] = 1
graph[6][2] = 1
# add edge 4-3 (or E-D in above figure)
graph[7][0] = 4
graph[7][1] = 3
graph[7][2] = -3
if (isNegCycleDisconnected()):
print("Yes")
else:
print("No")
# This code is contributed by mohit kumar 29
C#
// A C# program for Bellman-Ford's single source
// shortest path algorithm.
using System;
using System.Collections.Generic;
public class GFG
{
// A structure to represent a weighted
// edge in graph
public
class Edge
{
public
int src, dest, weight;
}
// A structure to represent a connected,
// directed and weighted graph
public
class Graph
{
// V-> Number of vertices,
// E-> Number of edges
public
int V, E;
// Graph is represented as
// an array of edges.
public
Edge []edge;
}
// Creates a graph with V vertices and E edges
static Graph createGraph(int V, int E)
{
Graph graph = new Graph();
graph.V = V;
graph.E = E;
graph.edge = new Edge[graph.E];
for(int i = 0; i < graph.E; i++)
{
graph.edge[i] = new Edge();
}
return graph;
}
// The main function that finds shortest distances
// from src to all other vertices using Bellman-
// Ford algorithm. The function also detects
// negative weight cycle
static bool isNegCycleBellmanFord(Graph graph,
int src,
int []dist)
{
int V = graph.V;
int E = graph.E;
// Step 1: Initialize distances from src
// to all other vertices as INFINITE
for(int i = 0; i < V; i++)
dist[i] = int.MaxValue;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times.
// A simple shortest path from src to any
// other vertex can have at-most |V| - 1
// edges
for(int i = 1; i <= V - 1; i++)
{
for(int j = 0; j < E; j++)
{
int u = graph.edge[j].src;
int v = graph.edge[j].dest;
int weight = graph.edge[j].weight;
if (dist[u] != int.MaxValue &&
dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
// Step 3: check for negative-weight cycles.
// The above step guarantees shortest distances
// if graph doesn't contain negative weight cycle.
// If we get a shorter path, then there
// is a cycle.
for(int i = 0; i < E; i++)
{
int u = graph.edge[i].src;
int v = graph.edge[i].dest;
int weight = graph.edge[i].weight;
if (dist[u] != int.MaxValue &&
dist[u] + weight < dist[v])
return true;
}
return false;
}
// Returns true if given graph has negative weight
// cycle.
static bool isNegCycleDisconnected(Graph graph)
{
int V = graph.V;
// To keep track of visited vertices
// to avoid recomputations.
bool []visited = new bool[V];
// This array is filled by Bellman-Ford
int []dist = new int[V];
// Call Bellman-Ford for all those vertices
// that are not visited
for(int i = 0; i < V; i++)
{
if (visited[i] == false)
{
// If cycle found
if (isNegCycleBellmanFord(graph, i, dist))
return true;
// Mark all vertices that are visited
// in above call.
for(int j = 0; j < V; j++)
if (dist[j] != int.MaxValue)
visited[j] = true;
}
}
return false;
}
// Driver Code
public static void Main(String[] args)
{
int V = 5, E = 8;
Graph graph = createGraph(V, E);
// Add edge 0-1 (or A-B in above figure)
graph.edge[0].src = 0;
graph.edge[0].dest = 1;
graph.edge[0].weight = -1;
// Add edge 0-2 (or A-C in above figure)
graph.edge[1].src = 0;
graph.edge[1].dest = 2;
graph.edge[1].weight = 4;
// Add edge 1-2 (or B-C in above figure)
graph.edge[2].src = 1;
graph.edge[2].dest = 2;
graph.edge[2].weight = 3;
// Add edge 1-3 (or B-D in above figure)
graph.edge[3].src = 1;
graph.edge[3].dest = 3;
graph.edge[3].weight = 2;
// Add edge 1-4 (or A-E in above figure)
graph.edge[4].src = 1;
graph.edge[4].dest = 4;
graph.edge[4].weight = 2;
// Add edge 3-2 (or D-C in above figure)
graph.edge[5].src = 3;
graph.edge[5].dest = 2;
graph.edge[5].weight = 5;
// Add edge 3-1 (or D-B in above figure)
graph.edge[6].src = 3;
graph.edge[6].dest = 1;
graph.edge[6].weight = 1;
// Add edge 4-3 (or E-D in above figure)
graph.edge[7].src = 4;
graph.edge[7].dest = 3;
graph.edge[7].weight = -3;
if (isNegCycleDisconnected(graph))
Console.WriteLine("Yes");
else
Console.WriteLine("No");
}
}
// This code is contributed by aashish1995
Javascript
输出 :
No
它是如何工作的?
正如所讨论的,对于给定的源,Bellman-Ford 算法首先计算路径中最多有一条边的最短距离。然后,它计算最多有 2 条边的最短路径,依此类推。在外循环的第 i 次迭代之后,计算最多具有 i 条边的最短路径。可以有一个最大值 |V| – 任何简单路径上的 1 条边,这就是外循环运行 |v| 的原因- 1次。如果存在负权重循环,则再进行一次迭代将给出一条较短的路线。
如何处理断开连接的图(如果从源无法访问循环)?
如果给定的图形断开连接,上述算法和程序可能无法工作。当所有顶点都可以从源顶点 0 到达时,它起作用。
为了处理断开的图,我们可以对距离无限的顶点重复该过程。
C++
// A C++ program for Bellman-Ford's single source
// shortest path algorithm.
#include
using namespace std;
// a structure to represent a weighted edge in graph
struct Edge {
int src, dest, weight;
};
// a structure to represent a connected, directed and
// weighted graph
struct Graph {
// V-> Number of vertices, E-> Number of edges
int V, E;
// graph is represented as an array of edges.
struct Edge* edge;
};
// Creates a graph with V vertices and E edges
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = new Graph;
graph->V = V;
graph->E = E;
graph->edge = new Edge[graph->E];
return graph;
}
// The main function that finds shortest distances
// from src to all other vertices using Bellman-
// Ford algorithm. The function also detects
// negative weight cycle
bool isNegCycleBellmanFord(struct Graph* graph,
int src, int dist[])
{
int V = graph->V;
int E = graph->E;
// Step 1: Initialize distances from src
// to all other vertices as INFINITE
for (int i = 0; i < V; i++)
dist[i] = INT_MAX;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times.
// A simple shortest path from src to any
// other vertex can have at-most |V| - 1
// edges
for (int i = 1; i <= V - 1; i++) {
for (int j = 0; j < E; j++) {
int u = graph->edge[j].src;
int v = graph->edge[j].dest;
int weight = graph->edge[j].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
// Step 3: check for negative-weight cycles.
// The above step guarantees shortest distances
// if graph doesn't contain negative weight cycle.
// If we get a shorter path, then there
// is a cycle.
for (int i = 0; i < E; i++) {
int u = graph->edge[i].src;
int v = graph->edge[i].dest;
int weight = graph->edge[i].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
return true;
}
return false;
}
// Returns true if given graph has negative weight
// cycle.
bool isNegCycleDisconnected(struct Graph* graph)
{
int V = graph->V;
// To keep track of visited vertices to avoid
// recomputations.
bool visited[V];
memset(visited, 0, sizeof(visited));
// This array is filled by Bellman-Ford
int dist[V];
// Call Bellman-Ford for all those vertices
// that are not visited
for (int i = 0; i < V; i++) {
if (visited[i] == false) {
// If cycle found
if (isNegCycleBellmanFord(graph, i, dist))
return true;
// Mark all vertices that are visited
// in above call.
for (int i = 0; i < V; i++)
if (dist[i] != INT_MAX)
visited[i] = true;
}
}
return false;
}
// Driver program to test above functions
int main()
{
/* Let us create the graph given in above example */
int V = 5; // Number of vertices in graph
int E = 8; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
// add edge 0-1 (or A-B in above figure)
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[0].weight = -1;
// add edge 0-2 (or A-C in above figure)
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 4;
// add edge 1-2 (or B-C in above figure)
graph->edge[2].src = 1;
graph->edge[2].dest = 2;
graph->edge[2].weight = 3;
// add edge 1-3 (or B-D in above figure)
graph->edge[3].src = 1;
graph->edge[3].dest = 3;
graph->edge[3].weight = 2;
// add edge 1-4 (or A-E in above figure)
graph->edge[4].src = 1;
graph->edge[4].dest = 4;
graph->edge[4].weight = 2;
// add edge 3-2 (or D-C in above figure)
graph->edge[5].src = 3;
graph->edge[5].dest = 2;
graph->edge[5].weight = 5;
// add edge 3-1 (or D-B in above figure)
graph->edge[6].src = 3;
graph->edge[6].dest = 1;
graph->edge[6].weight = 1;
// add edge 4-3 (or E-D in above figure)
graph->edge[7].src = 4;
graph->edge[7].dest = 3;
graph->edge[7].weight = -3;
if (isNegCycleDisconnected(graph))
cout << "Yes";
else
cout << "No";
return 0;
}
Java
// A Java program for Bellman-Ford's single source
// shortest path algorithm.
import java.util.*;
class GFG{
// A structure to represent a weighted
// edge in graph
static class Edge
{
int src, dest, weight;
}
// A structure to represent a connected,
// directed and weighted graph
static class Graph
{
// V-> Number of vertices,
// E-> Number of edges
int V, E;
// Graph is represented as
// an array of edges.
Edge edge[];
}
// Creates a graph with V vertices and E edges
static Graph createGraph(int V, int E)
{
Graph graph = new Graph();
graph.V = V;
graph.E = E;
graph.edge = new Edge[graph.E];
for(int i = 0; i < graph.E; i++)
{
graph.edge[i] = new Edge();
}
return graph;
}
// The main function that finds shortest distances
// from src to all other vertices using Bellman-
// Ford algorithm. The function also detects
// negative weight cycle
static boolean isNegCycleBellmanFord(Graph graph,
int src,
int dist[])
{
int V = graph.V;
int E = graph.E;
// Step 1: Initialize distances from src
// to all other vertices as INFINITE
for(int i = 0; i < V; i++)
dist[i] = Integer.MAX_VALUE;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times.
// A simple shortest path from src to any
// other vertex can have at-most |V| - 1
// edges
for(int i = 1; i <= V - 1; i++)
{
for(int j = 0; j < E; j++)
{
int u = graph.edge[j].src;
int v = graph.edge[j].dest;
int weight = graph.edge[j].weight;
if (dist[u] != Integer.MAX_VALUE &&
dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
// Step 3: check for negative-weight cycles.
// The above step guarantees shortest distances
// if graph doesn't contain negative weight cycle.
// If we get a shorter path, then there
// is a cycle.
for(int i = 0; i < E; i++)
{
int u = graph.edge[i].src;
int v = graph.edge[i].dest;
int weight = graph.edge[i].weight;
if (dist[u] != Integer.MAX_VALUE &&
dist[u] + weight < dist[v])
return true;
}
return false;
}
// Returns true if given graph has negative weight
// cycle.
static boolean isNegCycleDisconnected(Graph graph)
{
int V = graph.V;
// To keep track of visited vertices
// to avoid recomputations.
boolean visited[] = new boolean[V];
Arrays.fill(visited, false);
// This array is filled by Bellman-Ford
int dist[] = new int[V];
// Call Bellman-Ford for all those vertices
// that are not visited
for(int i = 0; i < V; i++)
{
if (visited[i] == false)
{
// If cycle found
if (isNegCycleBellmanFord(graph, i, dist))
return true;
// Mark all vertices that are visited
// in above call.
for(int j = 0; j < V; j++)
if (dist[j] != Integer.MAX_VALUE)
visited[j] = true;
}
}
return false;
}
// Driver Code
public static void main(String[] args)
{
int V = 5, E = 8;
Graph graph = createGraph(V, E);
// Add edge 0-1 (or A-B in above figure)
graph.edge[0].src = 0;
graph.edge[0].dest = 1;
graph.edge[0].weight = -1;
// Add edge 0-2 (or A-C in above figure)
graph.edge[1].src = 0;
graph.edge[1].dest = 2;
graph.edge[1].weight = 4;
// Add edge 1-2 (or B-C in above figure)
graph.edge[2].src = 1;
graph.edge[2].dest = 2;
graph.edge[2].weight = 3;
// Add edge 1-3 (or B-D in above figure)
graph.edge[3].src = 1;
graph.edge[3].dest = 3;
graph.edge[3].weight = 2;
// Add edge 1-4 (or A-E in above figure)
graph.edge[4].src = 1;
graph.edge[4].dest = 4;
graph.edge[4].weight = 2;
// Add edge 3-2 (or D-C in above figure)
graph.edge[5].src = 3;
graph.edge[5].dest = 2;
graph.edge[5].weight = 5;
// Add edge 3-1 (or D-B in above figure)
graph.edge[6].src = 3;
graph.edge[6].dest = 1;
graph.edge[6].weight = 1;
// Add edge 4-3 (or E-D in above figure)
graph.edge[7].src = 4;
graph.edge[7].dest = 3;
graph.edge[7].weight = -3;
if (isNegCycleDisconnected(graph))
System.out.println("Yes");
else
System.out.println("No");
}
}
// This code is contributed by adityapande88
Python3
# A Python3 program for Bellman-Ford's single source
# shortest path algorithm.
# The main function that finds shortest distances
# from src to all other vertices using Bellman-
# Ford algorithm. The function also detects
# negative weight cycle
def isNegCycleBellmanFord(src, dist):
global graph, V, E
# Step 1: Initialize distances from src
# to all other vertices as INFINITE
for i in range(V):
dist[i] = 10**18
dist[src] = 0
# Step 2: Relax all edges |V| - 1 times.
# A simple shortest path from src to any
# other vertex can have at-most |V| - 1
# edges
for i in range(1,V):
for j in range(E):
u = graph[j][0]
v = graph[j][1]
weight = graph[j][2]
if (dist[u] != 10**18 and dist[u] + weight < dist[v]):
dist[v] = dist[u] + weight
# Step 3: check for negative-weight cycles.
# The above step guarantees shortest distances
# if graph doesn't contain negative weight cycle.
# If we get a shorter path, then there
# is a cycle.
for i in range(E):
u = graph[i][0]
v = graph[i][1]
weight = graph[i][2]
if (dist[u] != 10**18 and dist[u] + weight < dist[v]):
return True
return False
# Returns true if given graph has negative weight
# cycle.
def isNegCycleDisconnected():
global V, E, graph
# To keep track of visited vertices to avoid
# recomputations.
visited = [0]*V
# memset(visited, 0, sizeof(visited))
# This array is filled by Bellman-Ford
dist = [0]*V
# Call Bellman-Ford for all those vertices
# that are not visited
for i in range(V):
if (visited[i] == 0):
# If cycle found
if (isNegCycleBellmanFord(i, dist)):
return True
# Mark all vertices that are visited
# in above call.
for i in range(V):
if (dist[i] != 10**18):
visited[i] = True
return False
# Driver code
if __name__ == '__main__':
# /* Let us create the graph given in above example */
V = 5 # Number of vertices in graph
E = 8 # Number of edges in graph
graph = [[0, 0, 0] for i in range(8)]
# add edge 0-1 (or A-B in above figure)
graph[0][0] = 0
graph[0][1] = 1
graph[0][2] = -1
# add edge 0-2 (or A-C in above figure)
graph[1][0] = 0
graph[1][1] = 2
graph[1][2] = 4
# add edge 1-2 (or B-C in above figure)
graph[2][0] = 1
graph[2][1] = 2
graph[2][2] = 3
# add edge 1-3 (or B-D in above figure)
graph[3][0] = 1
graph[3][1] = 3
graph[3][2] = 2
# add edge 1-4 (or A-E in above figure)
graph[4][0] = 1
graph[4][1] = 4
graph[4][2] = 2
# add edge 3-2 (or D-C in above figure)
graph[5][0] = 3
graph[5][1] = 2
graph[5][2] = 5
# add edge 3-1 (or D-B in above figure)
graph[6][0] = 3
graph[6][1] = 1
graph[6][2] = 1
# add edge 4-3 (or E-D in above figure)
graph[7][0] = 4
graph[7][1] = 3
graph[7][2] = -3
if (isNegCycleDisconnected()):
print("Yes")
else:
print("No")
# This code is contributed by mohit kumar 29
C#
// A C# program for Bellman-Ford's single source
// shortest path algorithm.
using System;
using System.Collections.Generic;
public class GFG
{
// A structure to represent a weighted
// edge in graph
public
class Edge
{
public
int src, dest, weight;
}
// A structure to represent a connected,
// directed and weighted graph
public
class Graph
{
// V-> Number of vertices,
// E-> Number of edges
public
int V, E;
// Graph is represented as
// an array of edges.
public
Edge []edge;
}
// Creates a graph with V vertices and E edges
static Graph createGraph(int V, int E)
{
Graph graph = new Graph();
graph.V = V;
graph.E = E;
graph.edge = new Edge[graph.E];
for(int i = 0; i < graph.E; i++)
{
graph.edge[i] = new Edge();
}
return graph;
}
// The main function that finds shortest distances
// from src to all other vertices using Bellman-
// Ford algorithm. The function also detects
// negative weight cycle
static bool isNegCycleBellmanFord(Graph graph,
int src,
int []dist)
{
int V = graph.V;
int E = graph.E;
// Step 1: Initialize distances from src
// to all other vertices as INFINITE
for(int i = 0; i < V; i++)
dist[i] = int.MaxValue;
dist[src] = 0;
// Step 2: Relax all edges |V| - 1 times.
// A simple shortest path from src to any
// other vertex can have at-most |V| - 1
// edges
for(int i = 1; i <= V - 1; i++)
{
for(int j = 0; j < E; j++)
{
int u = graph.edge[j].src;
int v = graph.edge[j].dest;
int weight = graph.edge[j].weight;
if (dist[u] != int.MaxValue &&
dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
// Step 3: check for negative-weight cycles.
// The above step guarantees shortest distances
// if graph doesn't contain negative weight cycle.
// If we get a shorter path, then there
// is a cycle.
for(int i = 0; i < E; i++)
{
int u = graph.edge[i].src;
int v = graph.edge[i].dest;
int weight = graph.edge[i].weight;
if (dist[u] != int.MaxValue &&
dist[u] + weight < dist[v])
return true;
}
return false;
}
// Returns true if given graph has negative weight
// cycle.
static bool isNegCycleDisconnected(Graph graph)
{
int V = graph.V;
// To keep track of visited vertices
// to avoid recomputations.
bool []visited = new bool[V];
// This array is filled by Bellman-Ford
int []dist = new int[V];
// Call Bellman-Ford for all those vertices
// that are not visited
for(int i = 0; i < V; i++)
{
if (visited[i] == false)
{
// If cycle found
if (isNegCycleBellmanFord(graph, i, dist))
return true;
// Mark all vertices that are visited
// in above call.
for(int j = 0; j < V; j++)
if (dist[j] != int.MaxValue)
visited[j] = true;
}
}
return false;
}
// Driver Code
public static void Main(String[] args)
{
int V = 5, E = 8;
Graph graph = createGraph(V, E);
// Add edge 0-1 (or A-B in above figure)
graph.edge[0].src = 0;
graph.edge[0].dest = 1;
graph.edge[0].weight = -1;
// Add edge 0-2 (or A-C in above figure)
graph.edge[1].src = 0;
graph.edge[1].dest = 2;
graph.edge[1].weight = 4;
// Add edge 1-2 (or B-C in above figure)
graph.edge[2].src = 1;
graph.edge[2].dest = 2;
graph.edge[2].weight = 3;
// Add edge 1-3 (or B-D in above figure)
graph.edge[3].src = 1;
graph.edge[3].dest = 3;
graph.edge[3].weight = 2;
// Add edge 1-4 (or A-E in above figure)
graph.edge[4].src = 1;
graph.edge[4].dest = 4;
graph.edge[4].weight = 2;
// Add edge 3-2 (or D-C in above figure)
graph.edge[5].src = 3;
graph.edge[5].dest = 2;
graph.edge[5].weight = 5;
// Add edge 3-1 (or D-B in above figure)
graph.edge[6].src = 3;
graph.edge[6].dest = 1;
graph.edge[6].weight = 1;
// Add edge 4-3 (or E-D in above figure)
graph.edge[7].src = 4;
graph.edge[7].dest = 3;
graph.edge[7].weight = -3;
if (isNegCycleDisconnected(graph))
Console.WriteLine("Yes");
else
Console.WriteLine("No");
}
}
// This code is contributed by aashish1995
Javascript
输出 :
No
使用 Floyd Warshall 检测负循环