📌  相关文章
📜  通过中间节点从源节点到目标节点的最小成本路径

📅  最后修改于: 2021-06-26 16:39:57             🧑  作者: Mango

给定无向加权图。任务是找到通过中间节点从源节点到目标节点的路径的最小开销。
注意:如果一条边缘移动了两次,则仅计算一次重量作为成本。

例子:

方法:假设采用从源到中间的路径P1,以及从中间到目标的路径P2。这两个路径之间可能有一些共同的边缘。因此,最佳路径将始终具有以下形式:对于任何节点U,步行都包括从源到U,从中间到U,从目的地到U的最短路径上的边。因此,如果dist(a,b )是节点a和b之间最短路径的成本,所需的最小成本路径将是min {dist(Source,U)+ dist(intermediate,U)+ dist(destination,U)} 对于所有U。通过对这3个节点执行Dijkstra的最短路径算法,可以找到所有节点距源,中间和目标的最小距离。
下面是上述方法的实现。

CPP
// CPP program to find minimum distance between
// source and destination node and visiting
// of intermediate node is compulsory
#include 
using namespace std;
#define MAXN 100005
 
// to store maped values of graph
vector > v[MAXN];
 
// to store distance of
// all nodes from the source node
int dist[MAXN];
 
// Dijkstra's algorithm to find
// shortest path from source to node
void dijkstra(int source, int n)
{
    // set all the vertices
    // distances as infinity
    for (int i = 0; i < n; i++)
        dist[i] = INT_MAX;
 
    // set all vertex as unvisited
    bool vis[n];
    memset(vis, false, sizeof vis);
 
    // make distance from source
    // vertex to source vertex is zero
    dist = 0;
 
    // // multiset do the job
    // as a min-priority queue
    multiset > s;
 
    // insert the source node with distance = 0
    s.insert({ 0, source });
 
    while (!s.empty()) {
        pair p = *s.begin();
        // pop the vertex with the minimum distance
        s.erase(s.begin());
 
        int x = p.second;
        int wei = p.first;
 
        // check if the popped vertex
        // is visited before
        if (vis[x])
            continue;
 
        vis[x] = true;
 
        for (int i = 0; i < v[x].size(); i++) {
            int e = v[x][i].first;
            int w = v[x][i].second;
 
            // check if the next vertex
            // distance could be minimized
            if (dist[x] + w < dist[e]) {
 
                dist[e] = dist[x] + w;
 
                // insert the next vertex
                // with the updated distance
                s.insert({ dist[e], e });
            }
        }
    }
}
 
// function to add edges in graph
void add_edge(int s, int t, int weight)
{
    v[s].push_back({ t, weight });
    v[t].push_back({ s, weight });
}
 
// function to find the minimum shortest path
int solve(int source, int destination,
               int intermediate, int n)
{
    int ans = INT_MAX;
 
    dijkstra(source, n);
 
    // store distance from source to
    // all other vertices
    int dsource[n];
    for (int i = 0; i < n; i++)
        dsource[i] = dist[i];
 
    dijkstra(destination, n);
    // store distance from destination
    // to all other vertices
    int ddestination[n];
    for (int i = 0; i < n; i++)
        destination[i] = dist[i];
 
    dijkstra(intermediate, n);
    // store distance from intermediate
    // to all other vertices
    int dintermediate[n];
    for (int i = 0; i < n; i++)
        dintermediate[i] = dist[i];
 
    // find required answer
    for (int i = 0; i < n; i++)
        ans = min(ans, dsource[i] + ddestination[i]
                                  + dintermediate[i]);
 
    return ans;
}
 
// Driver code
int main()
{
 
    int n = 4;
    int source = 0, destination = 2, intermediate = 3;
 
    // add edges in graph
    add_edge(0, 1, 1);
    add_edge(1, 2, 2);
    add_edge(1, 3, 3);
 
    // function call for minimum shortest path
    cout << solve(source, destination, intermediate, n);
 
    return 0;
}


输出:
6

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

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。