给定一个有N个顶点和M 个边的连通图。任务是找到从源顶点到目标顶点的最短路径,使得最短路径中相邻边权重之间的差异从正变为负,反之亦然(Weight(E1) > Weight(E2) < Weight(E3) … .)如果不存在这样的路径,则打印-1 。
例子:
Input: source = 4, destination = 3
Output: 19
4 – 2 – 1 – 3 (Edge Weights: 8, 3, 10) and 4 – 1 – 2 – 3 (Edge Weights: 6, 3, 10) are the only valid paths.
Second path takes the minimum cost i.e. 19.
Input: source = 2, destination = 4
Output: -1
No such path exists.
方法:这里,我们需要保留相邻列表的两个副本,一个用于正差,另一个用于负差。使用 Dijkstras 算法中的优先队列并一次保留四个变量,即,
- cost:存储到当前节点的路径成本。
- stage:一个整数变量,用于告诉下一个需要取什么元素,如果前一个值为负,则需要取正值,否则取负。
- weight:最后访问节点的权重。
- 顶点:上次访问的顶点。
对于每个顶点,根据所需条件(阶段值)推动相邻顶点。查看代码以获得更好的理解。
下面是上述方法的实现:
// 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 现场工作专业课程和学生竞争性编程现场课程。