Problem p01146 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>

using namespace std;

#define LOG(...) fprintf(stderr, __VA_ARGS__)
// #define LOG(...)
#define FOR(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define RFOR(i, a, b) for (int i = (int)(b - 1); i >= (int)(a); --i)
#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
#define RREP(i, n) for (int i = (int)(n - 1); i >= 0; --i)
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EXIST(s, e) ((s).find(e) != (s).end())
#define SORT(c) sort(ALL(c))
#define RSORT(c) sort(RALL(c))
#define SZ(a) ((int)(a).size())
#define BIT(x, i) (((x) >> (i)) & 1)
#define SQ(x) ((x) * (x))

typedef long long ll;
typedef unsigned long long ull;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vb> vvb;
typedef vector<vi> vvi;
typedef vector<vll> vvll;
typedef vector<char> vc;
typedef vector<vc> vvc;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define INF 1e8

struct Edge {
  int v, cost;
};

struct P {
  int v, cost;
  int life;

  bool operator>(const P &p) const {
    if (cost != p.cost)
      return cost > p.cost;
    return life > p.life;
  }
};

int main() {
  int town_n, life, freeze_n, road_n, start, goal;
  while (cin >> town_n >> life >> freeze_n >> road_n >> start >> goal, town_n) {
    vector<vector<Edge>> E(town_n);
    vb freeze(town_n);
    REP(i, freeze_n) {
      int a;
      cin >> a;
      freeze[a] = true;
    }
    REP(i, road_n) {
      int a, b, c;
      cin >> a >> b >> c;
      E[a].push_back({b, c});
      E[b].push_back({a, c});
    }

    vvi G(town_n, vi(life + 1, INF));
    G[start][life] = 0;

    priority_queue<P, vector<P>, greater<P>> que;
    que.push({start, 0, life});
    while (!que.empty()) {
      P p = que.top();
      que.pop();
      if (p.v == goal) {
        cout << p.cost << endl;
        goto END;
      }

      if (G[p.v][p.life] < p.cost)
        continue;

      for (Edge to : E[p.v]) {
        if (p.life >= to.cost) {
          int l = p.life - to.cost;
          REP(i, life + 1) {
            if (freeze[to.v] || i == 0) {
              if (l + i <= life) {
                int cost = p.cost + to.cost + i;
                if (G[to.v][l + i] > cost) {
                  G[to.v][l + i] = cost;
                  que.push({to.v, cost, l + i});
                }
              }
            }
          }
        }
      }
    }
    cout << "Help!" << endl;
  END : {}
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define LOG(...) printf(__VA_ARGS__)
// #define LOG(...)
#define REP(i, n) for (int i = 0; i < (int)n; ++i)

typedef long long ll;
typedef unsigned long long ull;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<vb> vvb;
typedef vector<vi> vvi;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define INF INT_MAX

struct edge {
  int to, cost;
};
typedef vector<edge> ve;
typedef vector<ve> vve;
typedef tuple<int, int, int, int> P; // total_cost, v, life, charged
typedef priority_queue<P, vector<P>, greater<P>> pq;

vi costs;
int V, max_life, freeze_n, road_n, start, goal;

void dijkstra(int c, int s, pq &que, const vve &G,
              vb &freeze) { // start_total_cost, start, que, G, freeze
  vi d(V, INF);
  d[s] = c;
  while (!que.empty()) {
    P p = que.top();
    que.pop();
    int cost = get<0>(p);
    int v = get<1>(p);
    int life = get<2>(p);
    int charged = get<3>(p);

    if (d[v] < cost)
      continue;
    REP(i, G[v].size()) {
      edge e = G[v][i];
      int l = life - e.cost;
      if (l < 0) {
        // 体力の関係上進むことができない
        continue;
      } else if (d[e.to] > d[v] + e.cost) {
        d[e.to] = d[v] + e.cost;
        if (e.to == goal) {
          costs.push_back(d[e.to] - l + charged);
        } else if (freeze[e.to]) {
          vb f = freeze;
          // 一度寄った冷凍施設には寄らない
          f[e.to] = false;

          // 回復せずに通過
          // pq que1;
          // que1.push(P(d[e.to], e.to, l, charged));
          // dijkstra(d[e.to], e.to, que1, G, f);

          // 最大まで回復して通過
          pq que2;
          que2.push(P(d[e.to], e.to, max_life, charged + max_life - l));
          dijkstra(d[e.to], e.to, que2, G, f);
        } else {
          que.push(P(d[e.to], e.to, l, charged));
        }
      }
    }
  }
}

int main() {
  while (cin >> V >> max_life >> freeze_n >> road_n >> start >> goal,
         V | max_life | freeze_n | road_n | start | goal) {
    vb freeze(V, false);
    REP(i, freeze_n) {
      int v;
      cin >> v;
      freeze[v] = true;
    }
    vve G(V);
    REP(i, road_n) {
      int from, to, cost;
      cin >> from >> to >> cost;
      G[from].push_back((edge){to, cost});
      G[to].push_back((edge){from, cost});
    }

    pq que;
    que.push(P(0, start, max_life, 0));
    dijkstra(0, start, que, G, freeze);
    if (costs.size() > 0) {
      cout << *min_element(costs.begin(), costs.end()) << endl;
      costs.clear();
    } else {
      cout << "Help!" << endl;
    }
  }
}