📜  通过降低边缘成本使用 Dijkstra 的最低成本

📅  最后修改于: 2021-10-25 03:23:21             🧑  作者: Mango

给定一个 N 节点和 M 条边的无向图,形式为 {X, Y, Z} ,使得XY之间有一条边,成本为Z 。任务是找到从源节点1遍历到目的节点N的最小成本,这样我们就可以将遍历过程中只有一条路径的成本减少 2。

例子:

方法:这个想法是考虑每条边,并尝试通过降低成本来最小化整体成本。主要思想是将源到目标之间的路径分解为源到任何顶点u路径(1 到 u)和从目标到任何顶点v即所有 u 和 v 的路径(n 到 v)。以下是步骤:

  1. 执行 Dijkstra 算法以找到来自源节点 1 的所有顶点的单个源最短路径,并将其作为dist_from_source[]存储在数组中。
  2. 执行 Dijkstra 算法以找到来自源节点 N 的所有顶点的单个源最短路径,并将其作为dist_from_dest[]存储在数组中。
  3. 将最小成本(比如minCost )初始化为最大值。
  4. 遍历给定的边,对于每条边,将当前成本减半,并将最小成本更新为:
  5. 在上述步骤之后打印 minCost的值。

下面是上述方法的实现:

C++14
// C++ program for the above approach
#include 
using namespace std;
#define INF 1e9
  
// Function for Dijkstra Algorithm to
// find single source shortest path
void dijkstra(int source, int n,
              vector >
                  adj[],
              vector& dist)
{
    // Resize dist[] to N and assign
    // any large value to it
    dist.resize(n, INF);
  
    // Initialise distance of source
    // node as 0
    dist = 0;
  
    // Using min-heap priority_queue
    // for sorting wrt edges_cost
    priority_queue,
                   vector >,
                   greater > >
        pq;
  
    // Push the current dist
    // and source to pq
    pq.push({ dist, source });
  
    // Until priority queue is empty
    while (!pq.empty()) {
  
        // Store the cost of linked
        // node to edges
        int u = pq.top().second;
        // int d = pq.top().first;
  
        // Pop the top node
        pq.pop();
  
        // Iterate over edges
        for (auto& edge : adj[u]) {
  
            // Find the starting and
            // ending vertex of edge
            int v = edge.first;
            int w = edge.second;
  
            // Update the distance of
            // node v to minimum of
            // dist[u] + w if it is
            // minimum
            if (dist[u] + w < dist[v]) {
                dist[v] = dist[u] + w;
                pq.push({ dist[v], v });
            }
        }
    }
}
  
// Function to find the minimum cost
// between node 1 to node n
void minCostPath(
    vector > >& edges,
    int n, int M)
{
  
    // To create Adjacency List
    vector > adj[100005];
  
    // Iterate over edges
    for (int i = 0; i < M; i++) {
  
        // Get source, destination and
        // edges of edges[i]
        int x = edges[i].first;
        int y = edges[i].second.first;
        int z = edges[i].second.second;
  
        // Create Adjacency List
        adj[x].push_back({ y, z });
        adj[y].push_back({ x, z });
    }
  
    // To store the cost from node 1
    // and node N
    vector dist_from_source;
    vector dist_from_dest;
  
    // Find the cost of travel between
    // source(1) to any vertex
    dijkstra(1, n + 1, adj, dist_from_source);
  
    // Find the cost of travel between
    // destination(n) to any vertex
    dijkstra(n, n + 1, adj, dist_from_dest);
  
    // Initialise the minimum cost
    int min_cost = dist_from_source[n];
  
    // Traverse the edges
    for (auto& it : edges) {
  
        // Get the edges
        int u = it.first;
        int v = it.second.first;
        int c = it.second.second;
  
        // Find the current cost from
        // node 1 to u and node u to v
        // and node v to N with only
        // current edge cost reduced
        // to half
        int cur_cost = dist_from_source[u]
                       + c / 2
                       + dist_from_dest[v];
  
        // Update the min_cost
        min_cost = min(min_cost, cur_cost);
    }
  
    // Print the minimum cost
    cout << min_cost << '\n';
}
  
// Driver Code
int main()
{
    // Give Nodes and Edges
    int N = 3;
    int M = 3;
  
    // Given Edges with cost
    vector > > edges;
  
    edges.push_back({ 2, { 3, 1 } });
    edges.push_back({ 1, { 3, 7 } });
    edges.push_back({ 2, { 1, 5 } });
  
    // Function Call
    minCostPath(edges, N, M);
    return 0;
}


输出:
3

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

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