给定一个具有N 个节点的图,一个节点S和Q查询每个由节点D和K 组成,任务是为每个查询找到由节点S到节点D的恰好K 条边组成的最短路径。如果不存在这样的路径,则打印-1 。
注意: K将始终小于2 * N 。
例子:
Input: N = 3, edges[][] = {{1, 2, 5}, {2, 3, 3}, {3, 1, 4}}, S = 1, Q = {{1, 0}, {2, 1}, {3, 1}, {3, 2}, {3, 5}}
Output: 0 5 -1 8 20
1. The shortest path from 1 to 1 using 0 edge will be 0.
2. The shortest path from 1 to 2 using 1 edge will be 5 i.e 1->2.
3. No path of 1 edge exists between nodes 1 and 3.
4. The shortest path from 1 to 3 using 2 edges will be 8 i.e 1->2->3.
5. The shortest path from 1 to 3 using 5 edges will be 20 i.e 1->2->3->1->2->3.
Input: N = 4, edges[][] = {{1, 2, 8}, {2, 3, 5}, {3, 4, 7}}, S = 1, Q = {{1, 0}, {2, 1}, {3, 1}, {3, 2}, {4, 5}}
Output: 0 8 -1 13 -1
方法:
- 这个问题可以在动态规划的帮助下解决,以创建线性解决方案。
- 初始化一个二维数组 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]:
dp[ edge.second ][ i ] = min(dp[ edge.second ][ i ], dp[ edge.first ][ i-1 ] + weight(edge))
- 对于 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