📜  两个城市之间的单源最短路径

📅  最后修改于: 2021-09-22 10:34:45             🧑  作者: Mango

给定一个N节点和E边的图,形式为{U, V, W} ,使得U 和 V之间存在权重为W 的边。你得到一个整数K和源src和目标dst 。任务是找到从给定源到目的地的K 个停靠点的最便宜的成本路径。
例子:

方法 1:使用深度优先搜索

  1. 探索当前节点并继续探索其子节点。
  2. 使用地图将访问过的节点与停靠点和距离成对存储为值。
  3. 如果键存在于映射中,则中断递归树。
  4. 为每个递归树找到答案(最小成本)并返回它。

下面是我们方法的实现。

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Structure to implement hashing to
// stores pairs in map
struct pair_hash {
    template 
    std::size_t
    operator()(const std::pair& pair) const
    {
        return std::hash()(pair.first)
               ^ std::hash()(pair.second);
    }
};
 
// DFS memoization
vector > adjMatrix;
typedef std::pair pair1;
unordered_map mp;
 
// Function to implement DFS Traversal
long DFSUtility(int node, int stops,
                int dst, int cities)
{
    // Base Case
    if (node == dst)
        return 0;
 
    if (stops < 0) {
        return INT_MAX;
    }
 
    pair key(node, stops);
 
    // Find value with key in a map
    if (mp.find(key) != mp.end()) {
        return mp[key];
    }
 
    long ans = INT_MAX;
 
    // Traverse adjacency matrix of
    // source node
    for (int neighbour = 0;
         neighbour < cities;
         ++neighbour) {
 
        long weight
            = adjMatrix[node][neighbour];
 
        if (weight > 0) {
 
            // Recursive DFS call for
            // child node
            long minVal
                = DFSUtility(neighbour,
                             stops - 1,
                             dst, cities);
 
            if (minVal + weight > 0)
                ans = min(ans,
                          minVal
                              + weight);
        }
    }
 
    mp[key] = ans;
 
    // Return ans
    return ans;
}
 
// Function to find the cheapest price
// from given source to destination
int findCheapestPrice(int cities,
                      vector >& flights,
                      int src, int dst, int stops)
{
 
    // Resize Adjacency Marix
    adjMatrix.resize(cities + 1,
                     vector(cities + 1, 0));
 
    // Traverse flight[][]
    for (auto item : flights) {
        // Create Adjacency Matrix
        adjMatrix[item[0]][item[1]] = item[2];
    }
 
    // DFS Call to find shortest path
    long ans = DFSUtility(src, stops,
                          dst, cities);
 
    // Return the cost
    return ans >= INT_MAX ? -1 : (int)ans;
    ;
}
 
// Driver Code
int main()
{
    // Input flight : {Source,
    // Destination, Cost}
    vector > flights
        = { { 4, 1, 1 }, { 1, 2, 3 }, { 0, 3, 2 }, { 0, 4, 10 }, { 3, 1, 1 }, { 1, 4, 3 } };
 
    // vec, n, stops, src, dst
    int stops = 2;
    int totalCities = 5;
    int sourceCity = 0;
    int destCity = 4;
 
    // Function Call
    long ans = findCheapestPrice(
        totalCities, flights,
        sourceCity, destCity,
        stops);
 
    cout << ans;
    return 0;
}


C++
// C++ program of the above approach
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
// BSF Memoization
typedef tuple tupl;
 
// Function to implement BFS
int findCheapestPrice(int cities,
                      vector >& flights,
                      int src, int dst, int stops)
{
    unordered_map > >
        adjList;
 
    // Traverse flight[][]
    for (auto flight : flights) {
 
        // Create Adjacency Matrix
        adjList[flight[0]].push_back(
            { flight[1], flight[2] });
    }
 
    // < city, distancefromsource > pair
    queue >
        q;
    q.push({ src, 0 });
 
    // Store the Result
    int srcDist = INT_MAX;
 
    // Traversing the Matrix
    while (!q.empty() && stops-- >= 0) {
 
        int qSize = q.size();
 
        for (int i = 0; i < qSize; i++) {
            pair curr = q.front();
            q.pop();
 
            for (auto next : adjList[curr.first]) {
 
                // If source distance is already
                // least the skip this iteration
                if (srcDist < curr.second
                                  + next.second)
                    continue;
 
                q.push({ next.first,
                         curr.second
                             + next.second });
 
                if (dst == next.first) {
                    srcDist = min(
                        srcDist, curr.second
                                     + next.second);
                }
            }
        }
    }
 
    // Returning the Answer
    return srcDist == INT_MAX ? -1 : srcDist;
}
 
// Driver Code
int main()
{
    // Input flight : {Source,
    // Destination, Cost}
    vector > flights
        = { { 4, 1, 1 }, { 1, 2, 3 }, { 0, 3, 2 }, { 0, 4, 10 }, { 3, 1, 1 }, { 1, 4, 3 } };
 
    // vec, n, stops, src, dst
    int stops = 2;
    int totalCities = 5;
 
    // Given source and destination
    int sourceCity = 0;
    int destCity = 4;
 
    // Function Call
    long ans = findCheapestPrice(
        totalCities, flights,
        sourceCity, destCity,
        stops);
    cout << ans;
    return 0;
}


C++
// C++ program for the above approach
#include 
#include 
using namespace std;
 
typedef tuple tupl;
long findCheapestPrice(int cities,
                       vector >& flights,
                       int src, int dst, int stops)
{
    // Adjacency Matrix
    vector > > adjList(cities);
 
    // Traverse flight[][]
    for (auto flight : flights) {
        // Create Adjacency Matrix
        adjList[flight[0]].push_back(
            { flight[1], flight[2] });
    }
 
    // Implementing Priority Queue
    priority_queue,
                   greater >
        pq;
 
    tupl t = make_tuple(0, src, stops);
    pq.push(t);
 
    // While PQ is not empty
    while (!pq.empty()) {
        tupl t = pq.top();
        pq.pop();
 
        if (src == dst)
            return 0;
 
        int cost = get<0>(t);
        int current = get<1>(t);
        int stop = get<2>(t);
 
        if (current == dst)
 
            // Return the Answer
            return cost;
 
        if (stop >= 0) {
            for (auto next : adjList[current]) {
 
                tupl t = make_tuple((cost
                                     + next.second),
                                    next.first,
                                    stop - 1);
                pq.push(t);
            }
        }
    }
    return -1;
}
 
int main()
{
    // Input flight : {Source,
    // Destination, Cost}
    vector > flights
        = { { 4, 1, 1 }, { 1, 2, 3 }, { 0, 3, 2 }, { 0, 4, 10 }, { 3, 1, 1 }, { 1, 4, 3 } };
 
    // vec, n, stops, src, dst
    int stops = 2;
    int totalCities = 5;
 
    // Given source and destination
    int sourceCity = 0;
    int destCity = 4;
 
    // Function Call
    long ans = findCheapestPrice(
        totalCities, flights,
        sourceCity, destCity, stops);
    cout << ans;
    return 0;
}


C++
// C++ program of the above Approach
#include 
#include 
using namespace std;
 
// Function to find the cheapest cost
// from source to destination using K stops
int findCheapestPrice(int cities,
                      vector >& flights,
                      int src, int dst, int stops)
{
    // Distance from source to all other nodes
    vector dist(cities, INT_MAX);
    dist[src] = 0;
 
    // Do relaxation for V-1 vertices
    // here we need for K stops so we
    // will do relaxation for k+1 stops
    for (int i = 0; i <= stops; i++) {
 
        vector intermediate(dist);
 
        for (auto flight : flights) {
 
            if (dist[flight[0]] != INT_MAX) {
                intermediate[flight[1]]
                    = min(intermediate[flight[1]],
                          dist[flight[0]]
                              + flight[2]);
            }
        }
 
        // Update the distance vector
        dist = intermediate;
    }
 
    // Return the final cost
    return dist[dst] == INT_MAX ? -1 : dist[dst];
}
 
// Driver Code
int main()
{
    // Input flight : {Source, Destination, Cost}
    vector > flights
        = { { 4, 1, 1 }, { 1, 2, 3 }, { 0, 3, 2 }, { 0, 4, 10 }, { 3, 1, 1 }, { 1, 4, 3 } };
 
    // vec, n, stops, src, dst
    int stops = 2;
    int totalCities = 5;
 
    // Given source and destination
    int sourceCity = 0;
    int destCity = 4;
 
    // Function Call
    long ans = findCheapestPrice(
        totalCities, flights, sourceCity,
        destCity, stops);
    cout << ans;
    return 0;
}


输出:
6

时间复杂度: O(V + E),其中 V 是节点数,E 是边。
辅助空间: O(V)

方法 2:使用广度优先 搜索

  1. 这个想法是使用 Queue 来执行 BFS Traversal。
  2. 从当前节点开始遍历,在队列中插入根节点。
  3. 遍历队列并探索当前节点及其兄弟节点。然后将节点的兄弟节点插入队列中。
  4. 在探索每个兄弟并在成本较低时继续推送队列中的条目并更新最小成本。
  5. 打印上述遍历后的最小成本。

下面是我们方法的实现:

C++

// C++ program of the above approach
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
// BSF Memoization
typedef tuple tupl;
 
// Function to implement BFS
int findCheapestPrice(int cities,
                      vector >& flights,
                      int src, int dst, int stops)
{
    unordered_map > >
        adjList;
 
    // Traverse flight[][]
    for (auto flight : flights) {
 
        // Create Adjacency Matrix
        adjList[flight[0]].push_back(
            { flight[1], flight[2] });
    }
 
    // < city, distancefromsource > pair
    queue >
        q;
    q.push({ src, 0 });
 
    // Store the Result
    int srcDist = INT_MAX;
 
    // Traversing the Matrix
    while (!q.empty() && stops-- >= 0) {
 
        int qSize = q.size();
 
        for (int i = 0; i < qSize; i++) {
            pair curr = q.front();
            q.pop();
 
            for (auto next : adjList[curr.first]) {
 
                // If source distance is already
                // least the skip this iteration
                if (srcDist < curr.second
                                  + next.second)
                    continue;
 
                q.push({ next.first,
                         curr.second
                             + next.second });
 
                if (dst == next.first) {
                    srcDist = min(
                        srcDist, curr.second
                                     + next.second);
                }
            }
        }
    }
 
    // Returning the Answer
    return srcDist == INT_MAX ? -1 : srcDist;
}
 
// Driver Code
int main()
{
    // Input flight : {Source,
    // Destination, Cost}
    vector > flights
        = { { 4, 1, 1 }, { 1, 2, 3 }, { 0, 3, 2 }, { 0, 4, 10 }, { 3, 1, 1 }, { 1, 4, 3 } };
 
    // vec, n, stops, src, dst
    int stops = 2;
    int totalCities = 5;
 
    // Given source and destination
    int sourceCity = 0;
    int destCity = 4;
 
    // Function Call
    long ans = findCheapestPrice(
        totalCities, flights,
        sourceCity, destCity,
        stops);
    cout << ans;
    return 0;
}
输出:
6

时间复杂度: O(Stops* N * N) 其中 N 是队列中城市和规模的乘积
辅助空间: O(N)

方法 3:使用Dijkstra 算法

  1. 更新所有顶点到源的距离。
  2. 与源不直接相连的顶点用无穷大标记,直接相连的顶点用正确的距离更新。
  3. 从源开始,提取下一个最小顶点。这将确保最低成本。
  4. 在每一步做边缘松弛: D 表示距离w 表示权重
    1. 如果 D[u] + w(u, z) < D[z] 那么
    2. D[z] = D[u] + w(u, z)

这是我们方法的实现:

C++

// C++ program for the above approach
#include 
#include 
using namespace std;
 
typedef tuple tupl;
long findCheapestPrice(int cities,
                       vector >& flights,
                       int src, int dst, int stops)
{
    // Adjacency Matrix
    vector > > adjList(cities);
 
    // Traverse flight[][]
    for (auto flight : flights) {
        // Create Adjacency Matrix
        adjList[flight[0]].push_back(
            { flight[1], flight[2] });
    }
 
    // Implementing Priority Queue
    priority_queue,
                   greater >
        pq;
 
    tupl t = make_tuple(0, src, stops);
    pq.push(t);
 
    // While PQ is not empty
    while (!pq.empty()) {
        tupl t = pq.top();
        pq.pop();
 
        if (src == dst)
            return 0;
 
        int cost = get<0>(t);
        int current = get<1>(t);
        int stop = get<2>(t);
 
        if (current == dst)
 
            // Return the Answer
            return cost;
 
        if (stop >= 0) {
            for (auto next : adjList[current]) {
 
                tupl t = make_tuple((cost
                                     + next.second),
                                    next.first,
                                    stop - 1);
                pq.push(t);
            }
        }
    }
    return -1;
}
 
int main()
{
    // Input flight : {Source,
    // Destination, Cost}
    vector > flights
        = { { 4, 1, 1 }, { 1, 2, 3 }, { 0, 3, 2 }, { 0, 4, 10 }, { 3, 1, 1 }, { 1, 4, 3 } };
 
    // vec, n, stops, src, dst
    int stops = 2;
    int totalCities = 5;
 
    // Given source and destination
    int sourceCity = 0;
    int destCity = 4;
 
    // Function Call
    long ans = findCheapestPrice(
        totalCities, flights,
        sourceCity, destCity, stops);
    cout << ans;
    return 0;
}
输出:
6

时间复杂度: O(E+V log V),其中 V 是节点数,E 是边。
辅助空间: O(V)

方法 4:使用Bellmon Ford

  1. 将源到所有顶点的距离初始化为无穷大,将到源本身的距离初始化为 0。
  2. 在每一步做边缘松弛:D 表示距离,w 表示权重
    • 如果 D[u] + w(u, z) < D[z] 那么 D[z] = D[u] + w(u, z)
  3. 该算法已被修改以解决给定的问题,而不是放松图 V-1 次,我们将针对给定的停止次数进行处理。

下面是上述方法的实现

C++

// C++ program of the above Approach
#include 
#include 
using namespace std;
 
// Function to find the cheapest cost
// from source to destination using K stops
int findCheapestPrice(int cities,
                      vector >& flights,
                      int src, int dst, int stops)
{
    // Distance from source to all other nodes
    vector dist(cities, INT_MAX);
    dist[src] = 0;
 
    // Do relaxation for V-1 vertices
    // here we need for K stops so we
    // will do relaxation for k+1 stops
    for (int i = 0; i <= stops; i++) {
 
        vector intermediate(dist);
 
        for (auto flight : flights) {
 
            if (dist[flight[0]] != INT_MAX) {
                intermediate[flight[1]]
                    = min(intermediate[flight[1]],
                          dist[flight[0]]
                              + flight[2]);
            }
        }
 
        // Update the distance vector
        dist = intermediate;
    }
 
    // Return the final cost
    return dist[dst] == INT_MAX ? -1 : dist[dst];
}
 
// Driver Code
int main()
{
    // Input flight : {Source, Destination, Cost}
    vector > flights
        = { { 4, 1, 1 }, { 1, 2, 3 }, { 0, 3, 2 }, { 0, 4, 10 }, { 3, 1, 1 }, { 1, 4, 3 } };
 
    // vec, n, stops, src, dst
    int stops = 2;
    int totalCities = 5;
 
    // Given source and destination
    int sourceCity = 0;
    int destCity = 4;
 
    // Function Call
    long ans = findCheapestPrice(
        totalCities, flights, sourceCity,
        destCity, stops);
    cout << ans;
    return 0;
}
输出:
6

时间复杂度: O(E*V),其中 V 是节点数,E 是边。
辅助空间: O(V)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。