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

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

#define rep(i, n) for (int(i) = 0; (i) < (int)(n); ++(i))
#define foreach(c, i)                                                          \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)

const int kInf = 1 << 28;

struct edge {
  int to, cost;
};

struct S {
  int v, p, cost;
  bool operator<(const S &other) const { return cost > other.cost; }
};

int N, M, L, K, A, H;
bool b[102];
vector<edge> es[102];

int d[102][102]; // d[i][j] -- 街i, 体力jにおける場合の最短時間

void solve() {
  priority_queue<S> q;

  rep(i, N + 1) rep(j, M + 1) d[i][j] = kInf;
  d[A][M] = 0;
  q.push((S){A, M, 0});

  while (!q.empty()) {
    S s = q.top();
    q.pop();
    int v = s.v, p = s.p, cost = s.cost;
    if (d[v][p] < cost)
      continue;
    // printf(">> v:%d p:%d cost:%d\\n", v, p, cost);

    rep(i, es[v].size()) {
      edge e = es[v][i];
      if (b[v]) {
        // 現在の街が冷凍施設がある
        // 体力を M まで回復して、移動することを試みる
        for (int j = 0; j + p <= M; ++j) {
          if (p + j - e.cost < 0)
            continue;
          if (d[e.to][p + j - e.cost] > cost + e.cost + j) {
            d[e.to][p + j - e.cost] = cost + e.cost + j;
            q.push((S){e.to, p + j - e.cost, cost + e.cost + j});
          }
        }
      } else {
        // 冷凍施設がない場合は、移動可能ならば
        // 体力を減らして移動
        if (p - e.cost < 0)
          continue;
        if (d[e.to][p - e.cost] > cost + e.cost) {
          d[e.to][p - e.cost] = cost + e.cost;
          q.push((S){e.to, p - e.cost, cost + e.cost});
        }
      }
    }
  }

  int ans = kInf;
  rep(i, M + 1) {
    // printf("d[H][%d] = %d\\n", i, d[H][i]);
    ans = min(ans, d[H][i]);
  }
  if (ans == kInf) {
    puts("Help!");
  } else {
    printf("%d\\n", ans);
  }
}

int main() {
  while (scanf("%d%d%d%d%d%d", &N, &M, &L, &K, &A, &H), N) {
    fill(b, b + N, false);

    int t;
    rep(i, L) {
      scanf("%d", &t);
      b[t] = true;
    }

    rep(i, N) es[i].clear();

    int x, y;
    rep(i, K) {
      scanf("%d%d%d", &x, &y, &t);
      es[x].push_back((edge){y, t});
      es[y].push_back((edge){x, t});
    }

    solve();
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

#define rep(i, n) for (int(i) = 0; (i) < (int)(n); ++(i))
#define foreach(c, i)                                                          \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)

const int kInf = 1 << 28;

struct edge {
  int to, cost;
};

struct S {
  int v, p, cost;
  bool operator<(const S &other) const { return cost < other.cost; }
};

int N, M, L, K, A, H;
bool b[102];
vector<edge> es[102];

int d[102][102]; // d[i][j] -- 街i, 体力jにおける場合の最短時間

void solve() {
  priority_queue<S> q;

  rep(i, N + 1) rep(j, M + 1) d[i][j] = kInf;
  d[A][M] = 0;
  q.push((S){A, M, 0});

  // rep(i,M+1) {
  //   printf("d[H][%d] = %d\\n", i, d[H][i]);
  // }

  while (!q.empty()) {
    S s = q.top();
    q.pop();
    int v = s.v, p = s.p, cost = s.cost;
    if (d[v][p] < cost)
      continue;
    // printf(">> v:%d p:%d cost:%d\\n", v, p, cost);

    rep(i, es[v].size()) {
      edge e = es[v][i];
      if (b[v]) {
        // 現在の街が冷凍施設がある
        // 体力を M まで回復して、移動することを試みる
        for (int j = 0; j + p <= M; ++j) {
          if (p + j - e.cost < 0)
            continue;
          if (d[e.to][p + j - e.cost] > cost + e.cost + j) {
            d[e.to][p + j - e.cost] = cost + e.cost + j;
            q.push((S){e.to, p + j - e.cost, cost + e.cost + j});
          }
        }
      } else {
        // 冷凍施設がない場合は、移動可能ならば
        // 体力を減らして移動
        if (p - e.cost < 0)
          continue;
        if (d[e.to][p - e.cost] > cost + e.cost) {
          d[e.to][p - e.cost] = cost + e.cost;
          q.push((S){e.to, p - e.cost, cost + e.cost});
        }
      }
    }
  }

  int ans = kInf;
  rep(i, M + 1) {
    // printf("d[H][%d] = %d\\n", i, d[H][i]);
    ans = min(ans, d[H][i]);
  }
  if (ans == kInf) {
    puts("Help!");
  } else {
    printf("%d\\n", ans);
  }
}

int main() {
  while (scanf("%d%d%d%d%d%d", &N, &M, &L, &K, &A, &H), N) {
    fill(b, b + N, false);

    int t;
    rep(i, L) {
      scanf("%d", &t);
      b[t] = true;
    }

    rep(i, N) es[i].clear();

    int x, y;
    rep(i, K) {
      scanf("%d%d%d", &x, &y, &t);
      es[x].push_back((edge){y, t});
      es[y].push_back((edge){x, t});
    }

    solve();
  }
  return 0;
}