#include <bits/stdc++.h>
using namespace std;
/*
Problem: Minimum Path Cost with One Free Continuous Segment
You are given a directed weighted graph with N nodes numbered from 0 to N - 1.
Each edge is given as:
[u, v, w] which means there is a directed edge from node u to node v with weight w.
You want to travel from node 0 to node N - 1 with minimum possible total cost.
------------------------------------------------------------
Special ability:
You are allowed to use a special override at most once.
If you use it:
- you choose one continuous block of edges on your path
- that block can contain at most K edges
- every edge inside that block becomes free
Important rules:
- the free edges must form one single continuous segment
- once you stop using the override, you cannot start it again
- you may also choose not to use the override at all
------------------------------------------------------------
Task:
Return the minimum possible cost to reach node N - 1 from node 0.
If there is no path, return -1.
------------------------------------------------------------
Example 1:
N = 4
edges = {{0,1,5}, {1,2,7}, {2,3,4}}
K = 2
Only path is:
0 -> 1 -> 2 -> 3
Normal cost = 5 + 7 + 4 = 16
If we make the first 2 edges free:
0 + 0 + 4 = 4
Answer = 4
------------------------------------------------------------
Main idea:
This is shortest path, but normal Dijkstra is not enough,
because the cost also depends on whether we have started or
finished using the override.
So we run Dijkstra on an expanded state space.
For every node, we keep track of the override status.
State meaning:
- 0 : override has not started yet
- 1..K : currently inside override, and exactly that many free edges have already been used
- K + 1 : override is already finished
Transitions:
From state 0:
- take next edge normally and stay in state 0
- or start override on this edge, make it free, and move to state 1
From state 1..K:
- stop override before taking next edge, then pay normally and move to state K+1
- or continue override for free if we have used fewer than K free edges
From state K+1:
- all future edges must be paid normally
Then the answer is the minimum distance among all states at node N - 1.
Time Complexity: O((N * K + M * K) log (N * K))
*/
class Solution {
public:
long long minimumTravelCost(int n, vector<vector<int>>& edges, int k) {
vector<vector<pair<int, int>>> graph(n);
for (auto& edge : edges) {
int u = edge[0];
int v = edge[1];
int w = edge[2];
graph[u].push_back({v, w});
}
const long long INF = (1LL << 62);
/*
Special case:
If k = 0, the override cannot make any edge free.
So this becomes a normal shortest path problem.
*/
if (k == 0) {
vector<long long> dist(n, INF);
priority_queue<
pair<long long, int>,
vector<pair<long long, int>>,
greater<pair<long long, int>>
> pq;
dist[0] = 0;
pq.push({0, 0});
while (!pq.empty()) {
auto [cost, u] = pq.top();
pq.pop();
if (cost != dist[u]) continue;
for (auto& [v, w] : graph[u]) {
if (dist[v] > cost + w) {
dist[v] = cost + w;
pq.push({dist[v], v});
}
}
}
return dist[n - 1] == INF ? -1 : dist[n - 1];
}
// For each node, we have states: 0, 1..k, k+1
int stateCount = k + 2;
// dist[u][state] = minimum cost to reach node u in this override state
vector<vector<long long>> dist(n, vector<long long>(stateCount, INF));
priority_queue<
tuple<long long, int, int>,
vector<tuple<long long, int, int>>,
greater<tuple<long long, int, int>>
> pq;
// Start at node 0 without using override
dist[0][0] = 0;
pq.push({0, 0, 0});
while (!pq.empty()) {
auto [cost, u, state] = pq.top();
pq.pop();
if (cost != dist[u][state]) continue;
for (auto& [v, w] : graph[u]) {
// Case 1: override has not started yet
if (state == 0) {
// Take this edge normally
if (dist[v][0] > cost + w) {
dist[v][0] = cost + w;
pq.push({dist[v][0], v, 0});
}
// Start override on this edge, so this edge is free
if (dist[v][1] > cost) {
dist[v][1] = cost;
pq.push({dist[v][1], v, 1});
}
}
// Case 2: currently inside the override segment
else if (1 <= state && state <= k) {
// Stop override before this edge, pay normally from now on
if (dist[v][k + 1] > cost + w) {
dist[v][k + 1] = cost + w;
pq.push({dist[v][k + 1], v, k + 1});
}
// Continue override on this edge if limit not exceeded
if (state < k && dist[v][state + 1] > cost) {
dist[v][state + 1] = cost;
pq.push({dist[v][state + 1], v, state + 1});
}
}
// Case 3: override already finished
else {
if (dist[v][k + 1] > cost + w) {
dist[v][k + 1] = cost + w;
pq.push({dist[v][k + 1], v, k + 1});
}
}
}
}
long long answer = INF;
for (int state = 0; state < stateCount; state++) {
answer = min(answer, dist[n - 1][state]);
}
return answer == INF ? -1 : answer;
}
};