📌  相关文章
📜  有向图和加权图中具有恰好为k的边的最短路径|套装2

📅  最后修改于: 2021-04-22 02:45:58             🧑  作者: Mango

给定一个有向加权图以及其中的两个顶点SD ,任务是找到从SD的最短路径,路径上恰好有K条边。如果不存在这样的路径,则打印-1。

例子:

方法:上一篇文章中已经讨论了用于此问题的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.

可以通过以下步骤计算问题的结果:

  1. 初始化一个数组,dis []的初始值为’inf’,但dis [S]为0。
  2. 当我等于1 – K时,运行一个循环
    • 使用初始值’inf’初始化一个数组dis1 []。
    • 对于图中的每个边,
      dis1 [edge.second] = min(dis1 [edge.second],dis [edge.first] + weight(edge))
  3. 如果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)