📜  使用 Floyd Warshall 检测负循环

📅  最后修改于: 2022-05-13 01:57:53.859000             🧑  作者: Mango

使用 Floyd Warshall 检测负循环

我们得到一个有向图。我们需要计算图是否有负循环。负循环是循环的总和为负的循环。

负循环

在图形的各种应用中都可以找到负权重。例如,如果我们遵循路径,我们可能会获得一些优势,而不是为路径支付成本。
例子:

Input : 4 4
        0 1 1
        1 2 -1
        2 3 -1
        3 0 -1

Output : Yes
The graph contains a negative cycle.

使用 Floyd Warshall 检测负循环

我们已经讨论了这个问题的基于贝尔曼福特算法的解决方案。
在这篇文章中,讨论了基于 Floyd Warshall 算法的解决方案,该解决方案适用于连通图和不连通图。
任何节点与其自身的距离始终为零。但在某些情况下,如本例中,当我们从 4 进一步遍历到 1 时,距离为 -2,即 1 到 1 的距离将变为 -2。这是我们的问题,我们只需要检查节点与自身的距离,如果结果为负,我们将检测所需的负循环。

C++
// C++ Program to check if there is a negative weight
// cycle using Floyd Warshall Algorithm
#include
using namespace std;
  
// Number of vertices in the graph
#define V 4
   
/* Define Infinite as a large enough value. This 
   value will be used for vertices not connected 
   to each other */
#define INF 99999
   
// A function to print the solution matrix
void printSolution(int dist[][V]);
   
// Returns true if graph has negative weight cycle
// else false.
bool negCyclefloydWarshall(int graph[][V])
{
    /* dist[][] will be the output matrix that will 
       finally have the shortest 
    distances between every pair of vertices */
    int dist[V][V], i, j, k;
   
    /* Initialize the solution matrix same as input
      graph matrix. Or we can say the initial values 
      of shortest distances are based on shortest 
      paths considering no intermediate vertex. */
    for (i = 0; i < V; i++)
        for (j = 0; j < V; j++)
            dist[i][j] = graph[i][j];
   
    /* Add all vertices one by one to the set of 
       intermediate vertices.
    ---> Before start of a iteration, we have shortest
         distances between all pairs of vertices such 
         that the shortest distances consider only the
         vertices in set {0, 1, 2, .. k-1} as intermediate 
         vertices.
    ----> After the end of a iteration, vertex no. k is 
          added to the set of intermediate vertices and 
          the set becomes {0, 1, 2, .. k} */
    for (k = 0; k < V; k++)
    {
        // Pick all vertices as source one by one
        for (i = 0; i < V; i++)
        {
            // Pick all vertices as destination for the
            // above picked source
            for (j = 0; j < V; j++)
            {
                // If vertex k is on the shortest path from
                // i to j, then update the value of dist[i][j]
                if (dist[i][k] + dist[k][j] < dist[i][j])
                        dist[i][j] = dist[i][k] + dist[k][j];
            }
        }
    }
  
    // If distance of any vertex from itself
    // becomes negative, then there is a negative
    // weight cycle.
    for (int i = 0; i < V; i++)
        if (dist[i][i] < 0)
            return true;
    return false; 
}
   
 // driver program
int main()
{
    /* Let us create the following weighted graph
            1
    (0)----------->(1)
    /|\             |
     |              |
  -1 |              | -1
     |             \|/
    (3)<-----------(2)
        -1       */
          
    int graph[V][V] = { {0   , 1   , INF , INF},
                        {INF , 0   , -1  , INF},
                        {INF , INF , 0   ,  -1},
                        {-1  , INF , INF ,   0}};
      
    if (negCyclefloydWarshall(graph))
       cout << "Yes";
    else
       cout << "No"; 
    return 0;
}


Java
// Java Program to check if there is a negative weight
// cycle using Floyd Warshall Algorithm
class GFG
{
  
    // Number of vertices in the graph
    static final int V = 4;
      
    /* Define Infinite as a large enough value. This 
    value will be used for vertices not connected 
    to each other */
    static final int INF = 99999;
      
    // Returns true if graph has negative weight cycle
    // else false.
    static boolean negCyclefloydWarshall(int graph[][])
    {
          
        /* dist[][] will be the output matrix that will 
        finally have the shortest 
        distances between every pair of vertices */
        int dist[][] = new int[V][V], i, j, k;
      
        /* Initialize the solution matrix same as input
        graph matrix. Or we can say the initial values 
        of shortest distances are based on shortest 
        paths considering no intermediate vertex. */
        for (i = 0; i < V; i++)
            for (j = 0; j < V; j++)
                dist[i][j] = graph[i][j];
      
        /* Add all vertices one by one to the set of 
        intermediate vertices.
        ---> Before start of a iteration, we have shortest
            distances between all pairs of vertices such 
            that the shortest distances consider only the
            vertices in set {0, 1, 2, .. k-1} as intermediate 
            vertices.
        ----> After the end of a iteration, vertex no. k is 
            added to the set of intermediate vertices and 
            the set becomes {0, 1, 2, .. k} */
        for (k = 0; k < V; k++)
        {
              
            // Pick all vertices as source one by one
            for (i = 0; i < V; i++)
            {
                  
                // Pick all vertices as destination for the
                // above picked source
                for (j = 0; j < V; j++)
                {
                      
                    // If vertex k is on the shortest path from
                    // i to j, then update the value of dist[i][j]
                    if (dist[i][k] + dist[k][j] < dist[i][j])
                            dist[i][j] = dist[i][k] + dist[k][j];
                }
            }
        }
      
        // If distance of any vertex from itself
        // becomes negative, then there is a negative
        // weight cycle.
        for (i = 0; i < V; i++)
            if (dist[i][i] < 0)
                return true;
  
        return false; 
    }
          
    // Driver code
    public static void main (String[] args)
    {
      
    /* Let us create the following weighted graph
                1
        (0)----------->(1)
        /|\               |
         |               |
      -1 |               | -1
         |                \|/
        (3)<-----------(2)
            -1     */
              
        int graph[][] = { {0, 1, INF, INF},
                          {INF, 0, -1, INF},
                          {INF, INF, 0, -1},
                          {-1, INF, INF, 0}};
          
        if (negCyclefloydWarshall(graph))
            System.out.print("Yes");
        else
            System.out.print("No"); 
    }
}
  
// This code is contributed by Anant Agarwal.


Python3
# Python Program to check
# if there is a
# negative weight
# cycle using Floyd
# Warshall Algorithm
  
   
# Number of vertices
# in the graph
V = 4
       
# Define Infinite as a
# large enough value. This 
# value will be used 
#for vertices not connected 
# to each other 
INF = 99999
       
# Returns true if graph has
# negative weight cycle
# else false.
def negCyclefloydWarshall(graph):
           
    # dist[][] will be the
    # output matrix that will 
    # finally have the shortest 
    # distances between every
    # pair of vertices 
    dist=[[0 for i in range(V+1)]for j in range(V+1)]
       
    # Initialize the solution
    # matrix same as input
    # graph matrix. Or we can
    # say the initial values 
    # of shortest distances
    # are based on shortest 
    # paths considering no
    # intermediate vertex. 
    for i in range(V):
        for j in range(V):
            dist[i][j] = graph[i][j]
       
    ''' Add all vertices one
        by one to the set of 
        intermediate vertices.
    ---> Before start of a iteration,
         we have shortest
        distances between all pairs
        of vertices such 
        that the shortest distances
        consider only the
        vertices in set {0, 1, 2, .. k-1}
        as intermediate vertices.
    ----> After the end of a iteration,
          vertex no. k is 
        added to the set of
        intermediate vertices and 
        the set becomes {0, 1, 2, .. k} '''
    for k in range(V):
      
        # Pick all vertices 
        # as source one by one
        for i in range(V):
                   
            # Pick all vertices as
            # destination for the
            # above picked source
            for j in range(V):
          
                # If vertex k is on
                # the shortest path from
                # i to j, then update
                # the value of dist[i][j]
                if (dist[i][k] + dist[k][j] < dist[i][j]):
                        dist[i][j] = dist[i][k] + dist[k][j]
   
    # If distance of any
    # vertex from itself
    # becomes negative, then
    # there is a negative
    # weight cycle.
    for i in range(V):
        if (dist[i][i] < 0):
            return True
   
    return False 
  
           
# Driver code
  
       
''' Let us create the
    following weighted graph
            1
    (0)----------->(1)
    /|\               |
     |               |
  -1 |               | -1
     |                \|/
    (3)<-----------(2)
        -1     '''
           
graph = [ [0, 1, INF, INF],
          [INF, 0, -1, INF],
          [INF, INF, 0, -1],
          [-1, INF, INF, 0]]
           
if (negCyclefloydWarshall(graph)):
    print("Yes")
else:
    print("No") 
  
# This code is contributed
# by Anant Agarwal.


C#
// C# Program to check if there
// is a negative weight cycle
// using Floyd Warshall Algorithm
  
using System;
  
namespace Cycle
{
public class GFG
{     
      
  
    // Number of vertices in the graph
    static int V = 4;
      
    /* Define Infinite as a large enough value. This 
    value will be used for vertices not connected 
    to each other */
    static int INF = 99999;
      
    // Returns true if graph has negative weight cycle
    // else false.
    static bool negCyclefloydWarshall(int [,]graph)
    {
          
        /* dist[][] will be the output matrix that will 
        finally have the shortest 
        distances between every pair of vertices */
        int [,]dist = new int[V,V];
        int i, j, k;
      
        /* Initialize the solution matrix same as input
        graph matrix. Or we can say the initial values 
        of shortest distances are based on shortest 
        paths considering no intermediate vertex. */
        for (i = 0; i < V; i++)
            for (j = 0; j < V; j++)
                dist[i,j] = graph[i,j];
      
        /* Add all vertices one by one to the set of 
        intermediate vertices.
        ---> Before start of a iteration, we have shortest
            distances between all pairs of vertices such 
            that the shortest distances consider only the
            vertices in set {0, 1, 2, .. k-1} as intermediate 
            vertices.
        ----> After the end of a iteration, vertex no. k is 
            added to the set of intermediate vertices and 
            the set becomes {0, 1, 2, .. k} */
        for (k = 0; k < V; k++)
        {
              
            // Pick all vertices as source one by one
            for (i = 0; i < V; i++)
            {
                  
                // Pick all vertices as destination for the
                // above picked source
                for (j = 0; j < V; j++)
                {
                      
                    // If vertex k is on the shortest path from
                    // i to j, then update the value of dist[i][j]
                    if (dist[i,k] + dist[k,j] < dist[i,j])
                            dist[i,j] = dist[i,k] + dist[k,j];
                }
            }
        }
      
        // If distance of any vertex from itself
        // becomes negative, then there is a negative
        // weight cycle.
        for (i = 0; i < V; i++)
            if (dist[i,i] < 0)
                return true;
  
        return false; 
    }
          
    // Driver code
    public static void Main()
    {
      
    /* Let us create the following weighted graph
                1
        (0)----------->(1)
        /|\             |
        |             |
    -1 |             | -1
        |             \|/
        (3)<-----------(2)
            -1     */
              
        int [,]graph = { {0, 1, INF, INF},
                        {INF, 0, -1, INF},
                        {INF, INF, 0, -1},
                        {-1, INF, INF, 0}};
          
        if (negCyclefloydWarshall(graph))
            Console.Write("Yes");
        else
            Console.Write("No"); 
    }
} 
}
  
// This code is contributed by Sam007.


Javascript


输出:

Yes