📌  相关文章
📜  图中从源 S 到目标 D 的最短路径,对于多个查询,恰好有 K 条边

📅  最后修改于: 2021-09-07 02:33:19             🧑  作者: Mango

给定一个具有N 个节点的图,一个节点SQ查询每个由节点DK 组成,任务是为每个查询找到由节点S到节点D的恰好K 条边组成的最短路径。如果不存在这样的路径,则打印-1

注意: K将始终小于2 * N

例子:

方法:

  • 这个问题可以在动态规划的帮助下解决,以创建线性解决方案。
  • 初始化一个二维数组 dp[N][2*N],初始值为 ‘inf’,除了 dp[S][0] 为 0。
  • 对图进行预处理,以找到 {0 到 N-1} 之间的每个边长度的每个节点与源的最短距离。数组 dp[][] 将用于存储预处理的结果。
  • 对于预处理,在 [1, 2*N-1] 范围内为 J 运行一个循环,以找到图中每条边的dp[X][J] ,其中dp[X][J]是从节点“S”到节点“X”的最短路径,总共使用了“J”条边。
  • 我们可以借助递推关系找到 dp[X][J+1]:
  • 对于 Q 中的每个查询,if(dp[X][k] == inf) 则返回 -1,否则返回 dp[X][k]

下面是上述方法的实现:

C++
// C++ implementation of the approach
 
#include 
using namespace std;
 
#define inf 100000000
 
// Function to find the shortest path
// between S and D with exactly K edges
void ansQueries(int s,
                vector, int> > ed,
                int n, vector > q)
{
 
    // To store the dp states
    int dp[n + 1][2 * n];
 
    // Initialising the dp[][] array
    for (int i = 0; i <= n; i++)
        dp[i][0] = inf;
    dp[s][0] = 0;
 
    // Pre-Processing
    for (int i = 1; i <= 2 * n - 1; i++) {
 
        // Initialising current state
        for (int j = 0; j <= n; j++)
            dp[j][i] = inf;
 
        // Updating current state
        for (auto it : ed) {
            dp[it.first.second][i]
                = min(
                    dp[it.first.second][i],
                    dp[it.first.first][i - 1] + it.second);
        }
    }
 
    for (int i = 0; i < q.size(); i++) {
        if (dp[q[i].first][q[i].second] == inf)
            cout << -1 << endl;
        else
            cout << dp[q[i].first][q[i].second]
                 << endl;
    }
}
 
// Driver code
int main()
{
    int n = 3;
    vector, int> > ed;
 
    // Edges
    ed = { { { 1, 2 }, 5 },
           { { 2, 3 }, 3 },
           { { 3, 1 }, 4 } };
 
    // Source
    int s = 1;
 
    // Queries
    vector > q = { { 1, 0 },
                                  { 2, 1 },
                                  { 3, 1 },
                                  { 3, 2 },
                                  { 3, 5 } };
 
    // Function to answer queries
    ansQueries(s, ed, n, q);
 
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
import java.lang.*;
import java.io.*;
 
class GFG{
 
static int inf = 100000000;
   
// Function to find the shortest path
// between S and D with exactly K edges
static void ansQueries(int s,
                       int[][] ed,
                int n, int[][] q)
{
     
    // To store the dp states
    int[][] dp = new int[n + 1][2 * n];
   
    // Initialising the dp[][] array
    for(int i = 0; i <= n; i++)
        dp[i][0] = inf;
         
    dp[s][0] = 0;
   
    // Pre-Processing
    for(int i = 1; i <= 2 * n - 1; i++)
    {
         
        // Initialising current state
        for(int j = 0; j <= n; j++)
            dp[j][i] = inf;
   
        // Updating current state
        for(int[] it : ed)
        {
            dp[it[1]][i] = Math.min(dp[it[1]][i],
                                    dp[it[0]][i - 1] +
                                       it[2]);
        }
    }
   
    for(int i = 0; i < q.length; i++)
    {
        if (dp[q[i][0]][q[i][1]] == inf) 
            System.out.println(-1); 
        else 
            System.out.println(dp[q[i][0]][q[i][1]]);
    }
}
   
// Driver code
public static void main(String[] args)
{
    int n = 3;
     
    // Edges
    int[][] ed = { { 1, 2, 5 },
                   { 2, 3, 3 },
                   { 3, 1, 4 } };
     
    // Source
    int s = 1;
     
    // Queries
    int[][] q = { { 1, 0 },
                  { 2, 1 },
                  { 3, 1 },
                  { 3, 2 },
                  { 3, 5 } };
     
    // Function to answer queries
    ansQueries(s, ed, n, q);
}
}
 
// This code is contributed by offbeat


Python3
# Python3 implementation of the approach
import sys,numpy as np
 
inf = sys.maxsize;
 
# Function to find the shortest path
# between S and D with exactly K edges
def ansQueries(s, ed, n, q) :
 
    # To store the dp states
    dp = np.zeros((n + 1, 2 * n));
 
    # Initialising the dp[][] array
    for i in range(n + 1) :
        dp[i][0] = inf;
         
    dp[s][0] = 0;
 
    # Pre-Processing
    for i in range( 1, 2 * n) :
 
        # Initialising current state
        for j in range( n + 1) :
            dp[j][i] = inf;
 
        # Updating current state
        for it in ed :
            dp[it[1]][i] = min( dp[it[1]][i],
                                dp[it[0]][i - 1] + ed[it]);
     
    for i in range(len(q)) :
        if (dp[q[i][0]][q[i][1]] == inf) :
            print(-1);
        else :
            print(dp[q[i][0]][q[i][1]]);
 
# Driver code
if __name__ == "__main__" :
 
    n = 3;
 
    # Edges
    ed = { ( 1, 2 ) : 5 ,
        ( 2, 3 ) : 3 ,
        ( 3, 1 ) : 4 };
 
    # Source
    s = 1;
 
    # Queries
    q = [
        ( 1, 0 ),
        ( 2, 1 ),
        ( 3, 1 ),
        ( 3, 2 ),
        ( 3, 5 )
        ];
 
    # Function to answer queries
    ansQueries(s, ed, n, q);
     
# This code is contributed by AnkitRai01


C#
// C# implementation of the approach
using System;
class GFG
{
  static int inf = 100000000;
 
  // Function to find the shortest path
  // between S and D with exactly K edges
  static void ansQueries(int s, int[][] ed, int n, int[][] q)
  {
 
    // To store the dp states
    int[, ] dp = new int[n + 1, 2 * n];
 
    // Initialising the dp[][] array
    for (int i = 0; i <= n; i++)
      dp[i, 0] = inf;
    dp[s, 0] = 0;
 
    // Pre-Processing
    for (int i = 1; i <= 2 * n - 1; i++)
    {
       
      // Initialising current state
      for (int j = 0; j <= n; j++)
        dp[j, i] = inf;
 
      // Updating current state
      foreach (int[] it in ed)
      {
        dp[it[1], i] = Math.Min(dp[it[1], i],
                                dp[it[0], i - 1] + it[2]);
      }
    }
 
    for (int i = 0; i < q.Length; i++)
    {
      if (dp[q[i][0], q[i][1]] == inf)
        Console.WriteLine(-1);
      else
        Console.WriteLine(dp[q[i][0], q[i][1]]);
    }
  }
 
  // Driver code
  public static void Main(string[] args)
  {
    int n = 3;
 
    // Edges
    int[][] ed = {
      new int[3]{1, 2, 5},
      new int[3]{2, 3, 3},
      new int[3]{3, 1, 4}
    };
 
    // Source
    int s = 1;
 
    // Queries
    int[][] q = {
      new int[2]{1, 0},
      new int[2]{2, 1},
      new int[2]{3, 1},
      new int[2]{3, 2},
      new int[2]{3, 5}
    };
 
    // Function to answer queries
    ansQueries(s, ed, n, q);
  }
}   
 
// This code is contributed by sanjeev2552


Javascript


输出:
0
5
-1
8
20

时间复杂度: O(Q + N*E)
空间复杂度: O(N*N)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live