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

📅  最后修改于: 2021-05-07 05:17:33             🧑  作者: Mango

给定N个节点的无向图,形式为{X,Y,Z}的M个边,使得XY之间存在边为Z的边。任务是找到从源节点1到目标节点N的最小开销,这样我们就可以将遍历期间仅一条路径的开销减少2。

例子:

方法:想法是考虑所有优势,并尝试通过降低成本来最大程度地降低总体成本。主要思想是将源到目标的路径分解为源到任何顶点u的路径,即path(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是节点数。