📌  相关文章
📜  有向图和加权图中两个节点之间的简单路径的最小成本

📅  最后修改于: 2021-05-13 23:33:16             🧑  作者: Mango

给定一个有向图,其中可能包含循环,每个边都有权重,因此任务是找到从给定源顶点“ s”到目标顶点“ t”的任何简单路径的最小成本。简单路径是从一个顶点到另一个顶点的路径,这样就不会多次访问一个顶点。如果没有简单的路径,则返回INF(infinite)。

该图以邻接矩阵表示形式给出,其中graph [i] [j]的值指示从顶点i到顶点j的边的权重,值INF(infinite)指示从i到j的边。

例子:

Input : V = 5, E = 6
        s = 0, t = 2
    graph[][] =      0   1   2   3   4  
                 0  INF -1  INF  1  INF
                 1  INF INF -2  INF INF
                 2  -3  INF INF INF INF
                 3  INF INF -1  INF INF
                 4  INF INF INF  2  INF
 
Output : -3 
Explanation : 
The minimum cost simple path between 0 and 2 is given by:
0 -----> 1 ------> 2 whose cost is (-1) + (-2) = (-3). 

Input : V = 5, E = 6
        s = 0, t = 4
    graph[][] =      0   1   2   3   4  
                 0  INF -7  INF -2  INF
                 1  INF INF -11 INF INF
                 2  INF INF INF INF INF
                 3  INF INF INF  3  -4
                 4  INF INF INF INF INF
 
Output : -6
Explanation : 
The minimum cost simple path between 0 and 2 is given by:
0 -----> 3 ------> 4 whose cost is (-2) + (-4) = (-6). 

方法 :
解决上述问题的主要思想是使用深度优先搜索的修改版本遍历从s到t的所有简单路径,并在其中找到最小成本路径。关于DFS的一项重要发现是它一次遍历一条路径,因此我们可以通过在离开节点之前将节点标记为未访问来使用DFS独立遍历单独的路径。
一个简单的解决方案是从s开始,转到所有相邻的顶点,然后对其他相邻的顶点进行递归操作,直到到达目的地。即使图形中存在负权重循环或自身边缘,该算法也将起作用。

下面是上述方法的实现:

C++
// C++ code for printing Minimum Cost
// Simple Path between two given nodes
// in a directed and weighted graph
#include 
using namespace std;
 
// Define number of vertices in
// the graph and infinite value
#define V 5
#define INF INT_MAX
 
// Function to do DFS through the nodes
int minimumCostSimplePath(int u, int destination,
                    bool visited[], int graph[][V])
{
 
    // check if we find the destination
    // then further cost will be 0
    if (u == destination)
        return 0;
 
    // marking the current node as visited
    visited[u] = 1;
 
    int ans = INF;
 
    // traverse through all
    // the adjacent nodes
    for (int i = 0; i < V; i++) {
        if (graph[u][i] != INF && !visited[i]) {
 
            // cost of the further path
            int curr = minimumCostSimplePath(i,
                        destination, visited, graph);
 
            // check if we have reached the destination
            if (curr < INF) {
 
                // Taking the minimum cost path
                ans = min(ans, graph[u][i] + curr);
            }
        }
    }
 
    // unmarking the current node
    // to make it available for other
    // simple paths
    visited[u] = 0;
 
    // returning the minimum cost
    return ans;
}
 
// driver code
int main()
{
 
    // initialising the graph
    int graph[V][V];
    for (int i = 0; i < V; i++) {
        for (int j = 0; j < V; j++) {
            graph[i][j] = INF;
        }
    }
 
    // marking all nodes as unvisited
    bool visited[V] = { 0 };
 
    // initialising the edges;
    graph[0][1] = -1;
    graph[0][3] = 1;
    graph[1][2] = -2;
    graph[2][0] = -3;
    graph[3][2] = -1;
    graph[4][3] = 2;
 
    // source and destination
    int s = 0, t = 2;
 
    // marking the source as visited
    visited[s] = 1;
 
    cout << minimumCostSimplePath(s, t,
                            visited, graph);
 
    return 0;
}


Java
// Java code for printing Minimum Cost
// Simple Path between two given nodes
// in a directed and weighted graph
import java.util.*;
import java.lang.*;
 
class GFG{
     
// Define number of vertices in
// the graph and infinite value
static int V = 5;
static int INF = Integer.MAX_VALUE;
 
// Function to do DFS through the nodes
static int minimumCostSimplePath(int u, int destination,
                                 boolean visited[],
                                 int graph[][])
{
     
    // Check if we find the destination
    // then further cost will be 0
    if (u == destination)
        return 0;
         
    // Marking the current node as visited
    visited[u] = true;
 
    int ans = INF;
 
    // Traverse through all
    // the adjacent nodes
    for(int i = 0; i < V; i++)
    {
        if (graph[u][i] != INF && !visited[i])
        {
             
            // Cost of the further path
            int curr = minimumCostSimplePath(i,
                        destination, visited, graph);
 
            // Check if we have reached the
            // destination
            if (curr < INF)
            {
                 
                // Taking the minimum cost path
                ans = Math.min(ans, graph[u][i] + curr);
            }
        }
    }
 
    // Unmarking the current node
    // to make it available for other
    // simple paths
    visited[u] = false;
 
    // Returning the minimum cost
    return ans;
}  
 
// Driver code
public static void main(String[] args)
{
     
    // Initialising the graph
    int graph[][] = new int[V][V];
    for(int i = 0; i < V; i++)
    {
        for(int j = 0; j < V; j++)
        {
            graph[i][j] = INF;
        }
    }
     
    // Marking all nodes as unvisited
    boolean visited[] = new boolean[V];
     
    // Initialising the edges;
    graph[0][1] = -1;
    graph[0][3] = 1;
    graph[1][2] = -2;
    graph[2][0] = -3;
    graph[3][2] = -1;
    graph[4][3] = 2;
     
    // Source and destination
    int s = 0, t = 2;
     
    // Marking the source as visited
    visited[s] = true;
     
    System.out.println(minimumCostSimplePath(s, t,
                            visited, graph));
}
}
 
// This code is contributed by offbeat


Python3
# Python3 code for printing Minimum Cost
# Simple Path between two given nodes
# in a directed and weighted graph
import sys
 
V = 5
INF = sys.maxsize
  
# Function to do DFS through the nodes
def minimumCostSimplePath(u, destination,
                          visited, graph):
 
    # Check if we find the destination
    # then further cost will be 0
    if (u == destination):
        return 0
  
    # Marking the current node as visited
    visited[u] = 1
  
    ans = INF
  
    # Traverse through all
    # the adjacent nodes
    for i in range(V):
        if (graph[u][i] != INF and not visited[i]):
  
            # Cost of the further path
            curr = minimumCostSimplePath(i, destination,
                                         visited, graph)
  
            # Check if we have reached the destination
            if (curr < INF):
  
                # Taking the minimum cost path
                ans = min(ans, graph[u][i] + curr)
             
    # Unmarking the current node
    # to make it available for other
    # simple paths
    visited[u] = 0
  
    # Returning the minimum cost
    return ans
     
# Driver code
if __name__=="__main__":
     
    # Initialising the graph
    graph = [[INF for j in range(V)]
                  for i in range(V)]
  
    # Marking all nodes as unvisited
    visited = [0 for i in range(V)]
  
    # Initialising the edges
    graph[0][1] = -1
    graph[0][3] = 1
    graph[1][2] = -2
    graph[2][0] = -3
    graph[3][2] = -1
    graph[4][3] = 2
     
    # Source and destination
    s = 0
    t = 2
  
    # Marking the source as visited
    visited[s] = 1
     
    print(minimumCostSimplePath(s, t, visited, graph))
  
# This code is contributed by rutvik_56


C#
// C# code for printing Minimum Cost
// Simple Path between two given nodes
// in a directed and weighted graph
using System;
using System.Collections;
using System.Collections.Generic;
class GFG
{
   
    // Define number of vertices in
    // the graph and infinite value
    static int V = 5;
    static int INF = int.MaxValue;
 
    // Function to do DFS through the nodes
    static int minimumCostSimplePath(int u, int destination,
                                     bool[] visited, int[, ] graph)
    {
       
        // Check if we find the destination
        // then further cost will be 0
        if (u == destination)
            return 0;
 
        // Marking the current node as visited
        visited[u] = true;
        int ans = INF;
 
        // Traverse through all
        // the adjacent nodes
        for (int i = 0; i < V; i++)
        {
            if (graph[u, i] != INF && !visited[i])
            {
               
                // Cost of the further path
                int curr = minimumCostSimplePath(i, destination,
                                                 visited, graph);
 
                // Check if we have reached the
                // destination
                if (curr < INF)
                {
                   
                    // Taking the minimum cost path
                    ans = Math.Min(ans, graph[u, i] + curr);
                }
            }
        }
 
        // Unmarking the current node
        // to make it available for other
        // simple paths
        visited[u] = false;
 
        // Returning the minimum cost
        return ans;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
       
        // Initialising the graph
        int[, ] graph = new int[V, V];
        for (int i = 0; i < V; i++)
        {
            for (int j = 0; j < V; j++)
            {
                graph[i, j] = INF;
            }
        }
 
        // Marking all nodes as unvisited
        bool[] visited = new bool[V];
 
        // Initialising the edges;
        graph[0, 1] = -1;
        graph[0, 3] = 1;
        graph[1, 2] = -2;
        graph[2, 0] = -3;
        graph[3, 2] = -1;
        graph[4, 3] = 2;
 
        // Source and destination
        int s = 0, t = 2;
 
        // Marking the source as visited
        visited[s] = true;
        Console.WriteLine(minimumCostSimplePath(s, t, visited, graph));
    }
}
 
// This code is contributed by sanjeev2552


输出:
-3