给定一个有向加权图以及其中的两个顶点S和D ,任务是找到从S到D的最短路径,路径上恰好有K条边。如果不存在这样的路径,则打印-1。
例子:
Input: N = 3, K = 2, ed = {{{1, 2}, 5}, {{2, 3}, 3}, {{3, 1}, 4}}, S = 1, D = 3
Output: 8
Explanation: The shortest path with two edges will be 1->2->3
Input: N = 3, K = 4, ed = {{{1, 2}, 5}, {{2, 3}, 3}, {{3, 1}, 4}}, S = 1, D = 3
Output: -1
Explanation: No path with edge length 4 exists from node 1 to 3
Input: N = 3, K = 5, ed = {{{1, 2}, 5}, {{2, 3}, 3}, {{3, 1}, 4}}, S = 1, D = 3
Output: 20
Explanation: Shortest path will be 1->2->3->1->2->3.
方法:上一篇文章中已经讨论了用于此问题的O(V ^ 3 * K)方法。在本文中,讨论了一种O(E * K)方法来解决此问题。
这个想法是使用动态编程来解决这个问题。
令dp [X] [J]为从节点S到节点X的最短路径,总共使用正好为J的边。使用此方法,dp [X] [J + 1]可以计算为:
dp[X][J+1] = min(arr[Y][J]+weight[{Y, X}])
for all Y which has an edge from Y to X.
可以通过以下步骤计算问题的结果:
- 初始化一个数组,dis []的初始值为’inf’,但dis [S]为0。
- 当我等于1 – K时,运行一个循环
- 使用初始值’inf’初始化一个数组dis1 []。
- 对于图中的每个边,
dis1 [edge.second] = min(dis1 [edge.second],dis [edge.first] + weight(edge))
- 如果dist [d]为无穷大,则返回-1,否则返回dist [d]。
下面是上述方法的实现:
C++
// C++ implementation of the above approach
#include
#define inf 100000000
using namespace std;
// Function to find the smallest path
// with exactly K edges
double smPath(int s, int d,
vector, int> > ed,
int n, int k)
{
// Array to store dp
int dis[n + 1];
// Initialising the array
for (int i = 0; i <= n; i++)
dis[i] = inf;
dis[s] = 0;
// Loop to solve DP
for (int i = 0; i < k; i++) {
// Initialising next state
int dis1[n + 1];
for (int j = 0; j <= n; j++)
dis1[j] = inf;
// Recurrence relation
for (auto it : ed)
dis1[it.first.second] = min(dis1[it.first.second],
dis[it.first.first]
+ it.second);
for (int i = 0; i <= n; i++)
dis[i] = dis1[i];
}
// Returning final answer
if (dis[d] == inf)
return -1;
else
return dis[d];
}
// Driver code
int main()
{
int n = 4;
vector, int> > ed;
// Input edges
ed = { { { 0, 1 }, 10 },
{ { 0, 2 }, 3 },
{ { 0, 3 }, 2 },
{ { 1, 3 }, 7 },
{ { 2, 3 }, 7 } };
// Source and Destination
int s = 0, d = 3;
// Number of edges in path
int k = 2;
// Calling the function
cout << smPath(s, d, ed, n, k);
}
Java
// Java implementation of the above approach
import java.util.ArrayList;
import java.util.Arrays;
class GFG{
static class Pair
{
K first;
V second;
public Pair(K first, V second)
{
this.first = first;
this.second = second;
}
}
static int inf = 100000000;
// Function to find the smallest path
// with exactly K edges
static int smPath(int s, int d,
ArrayList, Integer>> ed,
int n, int k)
{
// Array to store dp
int[] dis = new int[n + 1];
// Initialising the array
Arrays.fill(dis, inf);
dis[s] = 0;
// Loop to solve DP
for(int i = 0; i < k; i++)
{
// Initialising next state
int[] dis1 = new int[n + 1];
Arrays.fill(dis1, inf);
// Recurrence relation
for(Pair, Integer> it : ed)
dis1[it.first.second] = Math.min(dis1[it.first.second],
dis[it.first.first] +
it.second);
for(int j = 0; j <= n; j++)
dis[j] = dis1[j];
}
// Returning final answer
if (dis[d] == inf)
return -1;
else
return dis[d];
}
// Driver code
public static void main(String[] args)
{
int n = 4;
// Input edges
ArrayList, Integer>> ed = new ArrayList<>(
Arrays.asList(
new Pair, Integer>(
new Pair(0, 1), 10),
new Pair, Integer>(
new Pair(0, 2), 3),
new Pair, Integer>(
new Pair(0, 3), 2),
new Pair, Integer>(
new Pair(1, 3), 7),
new Pair, Integer>(
new Pair(2, 3), 7)
)
);
// Source and Destination
int s = 0, d = 3;
// Number of edges in path
int k = 2;
// Calling the function
System.out.println(smPath(s, d, ed, n, k));
}
}
// This code is contributed by sanjeev2552
Python3
# Python3 implementation of the above approach
inf = 100000000
# Function to find the smallest path
# with exactly K edges
def smPath(s, d, ed, n, k):
# Array to store dp
dis = [inf] * (n + 1)
dis[s] = 0
# Loop to solve DP
for i in range(k):
# Initialising next state
dis1 = [inf] * (n + 1)
# Recurrence relation
for it in ed:
dis1[it[1]] = min(dis1[it[1]],
dis[it[0]]+ it[2])
for i in range(n + 1):
dis[i] = dis1[i]
# Returning final answer
if (dis[d] == inf):
return -1
else:
return dis[d]
# Driver code
if __name__ == '__main__':
n = 4
# Input edges
ed = [ [0, 1 ,10],
[ 0, 2 ,3],
[ 0, 3 ,2],
[ 1, 3 ,7],
[ 2, 3 ,7] ]
# Source and Destination
s = 0
d = 3
# Number of edges in path
k = 2
# Calling the function
print(smPath(s, d, ed, n, k))
# This code is contributed by mohit kumar 29
10
时间复杂度: O(E * K)
空间复杂度: O(N)