📌  相关文章
📜  从源到目的地的最短路径,使得沿路径的边权重交替增加和减少

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

给定一个有N个顶点和M 个边的连通图。任务是找到从源顶点到目标顶点的最短路径,使得最短路径中相邻边权重之间的差异从正变为负,反之亦然(Weight(E1) > Weight(E2) < Weight(E3) … .)如果不存在这样的路径,则打印-1

例子:

方法:这里,我们需要保留相邻列表的两个副本,一个用于正差,另一个用于负差。使用 Dijkstras 算法中的优先队列并一次保留四个变量,即,

  1. cost:存储到当前节点的路径成本。
  2. stage:一个整数变量,用于告诉下一个需要取什么元素,如果前一个值为负,则需要取正值,否则取负。
  3. weight:最后访问节点的权重。
  4. 顶点:上次访问的顶点。

对于每个顶点,根据所需条件(阶段值)推动相邻顶点。查看代码以获得更好的理解。

下面是上述方法的实现:

// C++ implementation of the approach
#include 
using namespace std;
#define N 100005
  
// To store the graph
vector > incr[N], decr[N];
int _incr[N], _decr[N], shortest[N];
  
int n, m, src, dest, MAXI = 1LL << 30;
  
// Function to add edges
void Add_edge(int x, int y, int w)
{
    incr[x].push_back({ w, y });
    incr[y].push_back({ w, x });
    decr[x].push_back({ -w, y });
    decr[y].push_back({ -w, x });
}
  
// Function to find the shortest distance from
// source to destination
int Modified_Dijkstra()
{
  
    // Total cost, stage, weight of previous, vertex
    priority_queue, pair > > q;
  
    // Sort the edges
    for (int i = 1; i <= n; i++) {
        sort(incr[i].begin(), incr[i].end());
        sort(decr[i].begin(), decr[i].end());
    }
  
    for (int i = 1; i <= n; i++)
        shortest[i] = MAXI;
  
    // Push the source vertex
    q.push({ { 0, 0 }, { 0, src } });
  
    while (!q.empty()) {
  
        // Take the top element in the queue
        pair, pair > FRONT = q.top();
  
        // Remove it from the queue
        q.pop();
  
        // Store all the values
        int cost = -FRONT.first.first;
        int stage = FRONT.first.second;
        int weight = FRONT.second.first;
        int v = FRONT.second.second;
  
        // Take the minimum cost for the vertex
        shortest[v] = min(shortest[v], cost);
  
        // If destination vertex has already been visited
        if (shortest[dest] != MAXI)
            break;
  
        // To make difference negative
        if (stage) {
  
            // Start from last not visited vertex
            for (int i = _incr[v]; i < incr[v].size(); i++) {
  
                // If we can take the ith vertex
                if (weight > incr[v][i].first)
                    q.push({ { -(cost + incr[v][i].first), 0 },
                             { incr[v][i].first, incr[v][i].second } });
                else {
  
                    // To keep the last not visited vertex
                    _incr[v] = i;
                    break;
                }
            }
        }
  
        // To make difference positive
        else {
  
            // Start from last not visited vertex
            for (int i = _decr[v]; i < decr[v].size(); i++) {
  
                // If we can take the ith vertex
                if (weight < -decr[v][i].first)
                    q.push({ { -(cost - decr[v][i].first), 1 },
                             { -decr[v][i].first, decr[v][i].second } });
                else {
  
                    // To keep the last not visited vertex
                    _decr[v] = i;
                    break;
                }
            }
        }
    }
  
    if (shortest[dest] == MAXI)
        return -1;
  
    return shortest[dest];
}
  
// Driver code
int main()
{
    n = 5, src = 4, dest = 3;
  
    // Adding edges
    Add_edge(4, 2, 8);
    Add_edge(1, 4, 6);
    Add_edge(2, 3, 10);
    Add_edge(3, 1, 10);
    Add_edge(1, 2, 3);
    Add_edge(3, 5, 3);
  
    cout << Modified_Dijkstra();
  
    return 0;
}
输出:
19

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