Skip to content

2093. Minimum Cost to Reach City With Discounts 👍

  • Time: $O(|E|\log |E|)$
  • Space: $O(|E|)$
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
struct T {
  int u;
  int d;
  int leftDiscounts;
  T(int u, int d, int leftDiscounts)
      : u(u), d(d), leftDiscounts(leftDiscounts) {}
};

class Solution {
 public:
  int minimumCost(int n, vector<vector<int>>& highways, int discounts) {
    vector<vector<pair<int, int>>> graph(n);
    auto compare = [](const T& a, const T& b) { return a.d > b.d; };
    priority_queue<T, vector<T>, decltype(compare)> minHeap(compare);
    unordered_map<int, int> minDiscounts;

    for (const vector<int>& h : highways) {
      const int city1 = h[0];
      const int city2 = h[1];
      const int toll = h[2];
      graph[city1].emplace_back(city2, toll);
      graph[city2].emplace_back(city1, toll);
    }

    minHeap.emplace(0, 0, discounts);

    while (!minHeap.empty()) {
      const auto [u, d, leftDiscounts] = minHeap.top();
      minHeap.pop();
      if (u == n - 1)
        return d;
      if (minDiscounts.count(u) && minDiscounts[u] >= leftDiscounts)
        continue;
      minDiscounts[u] = leftDiscounts;
      for (const auto& [v, w] : graph[u]) {
        minHeap.emplace(v, d + w, leftDiscounts);
        if (leftDiscounts > 0)
          minHeap.emplace(v, d + w / 2, leftDiscounts - 1);
      }
    }

    return -1;
  }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class T {
  public int u;
  public int d;
  public int leftDiscounts;
  public T(int u, int d, int leftDiscounts) {
    this.u = u;
    this.d = d;
    this.leftDiscounts = leftDiscounts;
  }
}

class Solution {
  public int minimumCost(int n, int[][] highways, int discounts) {
    List<Pair<Integer, Integer>>[] graph = new List[n];
    Queue<T> minHeap = new PriorityQueue<>((a, b) -> a.d - b.d);
    Map<Integer, Integer> minDiscounts = new HashMap<>();

    for (int i = 0; i < graph.length; i++)
      graph[i] = new ArrayList<>();

    for (int[] h : highways) {
      final int city1 = h[0];
      final int city2 = h[1];
      final int toll = h[2];
      graph[city1].add(new Pair<>(city2, toll));
      graph[city2].add(new Pair<>(city1, toll));
    }

    minHeap.offer(new T(0, 0, discounts));

    while (!minHeap.isEmpty()) {
      final int u = minHeap.peek().u;
      final int d = minHeap.peek().d;
      final int leftDiscounts = minHeap.poll().leftDiscounts;
      if (u == n - 1)
        return d;
      if (minDiscounts.getOrDefault(u, -1) >= leftDiscounts)
        continue;
      minDiscounts.put(u, leftDiscounts);
      for (Pair<Integer, Integer> pair : graph[u]) {
        final int v = pair.getKey();
        final int w = pair.getValue();
        minHeap.offer(new T(v, d + w, leftDiscounts));
        if (leftDiscounts > 0)
          minHeap.offer(new T(v, d + w / 2, leftDiscounts - 1));
      }
    }
    return -1;
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution:
  def minimumCost(self, n: int, highways: List[List[int]], discounts: int) -> int:
    graph = [[] for _ in range(n)]
    minHeap = [(0, 0, discounts)]  # (d, u, leftDiscounts)
    minDiscounts = {}

    for city1, city2, toll in highways:
      graph[city1].append((city2, toll))
      graph[city2].append((city1, toll))

    while minHeap:
      d, u, leftDiscounts = heapq.heappop(minHeap)
      if u == n - 1:
        return d
      if u in minDiscounts and minDiscounts[u] >= leftDiscounts:
        continue
      minDiscounts[u] = leftDiscounts
      for v, w in graph[u]:
        heapq.heappush(minHeap, (d + w, v, leftDiscounts))
        if leftDiscounts > 0:
          heapq.heappush(minHeap, (d + w // 2, v, leftDiscounts - 1))

    return -1