Problem p01146 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>

using namespace std;

#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
typedef int Weight;
typedef pair<Weight, int> Data;
// enable reduce
struct Heap {
  shared_ptr<Heap> l, r, p;
  Data val;
  Heap(Data v) : val(v) {}
  Data top() { return val; }
};
int cnt1, cnt2;
shared_ptr<Heap> meld(shared_ptr<Heap> a, shared_ptr<Heap> b,
                      shared_ptr<Heap> p = nullptr) {
  ++cnt1;
  if (p == nullptr)
    ++cnt2;
  if (!a) {
    if (b)
      b->p = p;
    return b;
  }
  if (!b) {
    if (a)
      a->p = p;
    return a;
  }
  if (a->val > b->val)
    swap(a, b);
  a->p = p;
  a->r = meld(a->r, b, a);
  swap(a->l, a->r);
  return a;
}
pair<shared_ptr<Heap>, shared_ptr<Heap>> push(shared_ptr<Heap> h, Data v) {
  auto n = make_shared<Heap>(v);
  return make_pair(meld(h, n), n);
}
shared_ptr<Heap> pop(shared_ptr<Heap> h) {
  if (h->l)
    h->l->p.reset();
  if (h->r)
    h->r->p.reset();
  return meld(h->l, h->r);
}
shared_ptr<Heap> reduce(shared_ptr<Heap> h, shared_ptr<Heap> root, Data v) {
  if (v > h->val)
    return root;
  h->val = v;
  if (!h->p)
    return root;
  if (h->val < h->p->val) {
    if (h->p->l && h->p->l == h) {
      h->p->l.reset();
      return meld(h, root);
    } else {
      h->p->r.reset();
      return meld(h, root);
    }
  } else
    return root;
}

Weight INF = 1000000000;
struct Edge {
  int src, dest;
  Weight weight;
  bool operator<(const Edge &rhs) const { return weight > rhs.weight; }
};

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void add_edge(Graph &g, int src, int dest, Weight weight) {
  g[src].push_back((Edge){src, dest, weight});
  g[dest].push_back((Edge){dest, src, weight});
}

template <typename G> void dijkstra(G &g, Array &d, int s) {
  int n = g.size();
  d.assign(n, INF);
  d[s] = 0;
  shared_ptr<Heap> que;
  vector<shared_ptr<Heap>> nodes(n);
  auto p = push(que, Data(0, s));
  que = p.first;
  nodes[s] = p.second;
  assert(que != nullptr);
  while (que) {
    Weight dist = que->top().first;
    int v = que->top().second;
    que = pop(que);
    nodes[v].reset();
    if (d[v] < dist)
      continue;
    REP(i, g(v).size()) {
      Edge e = g(v)[i];
      if (d[e.dest] > d[v] + e.weight) {
        d[e.dest] = d[v] + e.weight;
        if (!nodes[e.dest]) {
          auto p = push(que, Data(d[e.dest], e.dest));
          que = p.first;
          nodes[e.dest] = p.second;
        } else {
          que = reduce(nodes[e.dest], que, Data(d[e.dest], e.dest));
        }
      }
    }
  }
}

struct G {
  Graph g;
  int m;
  vector<bool> f;
  G(Graph &g, int m, vector<bool> &f) : g(g), m(m), f(f) {}
  Edges operator()(int i) {
    int j = i / (m + 1);
    int k = i % (m + 1);
    Edges es;
    REP(l, g[j].size()) {
      if (k + g[j][l].weight > m)
        continue;
      es.push_back((Edge){i, g[j][l].dest * (m + 1) + k + g[j][l].weight,
                          g[j][l].weight});
    }
    if (f[j] && k)
      es.push_back((Edge){i, i - 1, 1});
    return es;
  }
  size_t size() const { return g.size() * (m + 1); }
};

int main() {
  while (1) {
    int n, m, l, k, a, h;
    cin >> n >> m >> l >> k >> a >> h;
    if (!n)
      break;
    vector<int> f(l);
    REP(i, l) cin >> f[i];
    Graph g(n);
    REP(i, k) {
      int s, t, c;
      cin >> s >> t >> c;
      add_edge(g, s, t, c);
    }
    vector<bool> fb(n, false);
    REP(i, l) fb[f[i]] = true;
    G gg(g, m, fb);
    Array d(gg.size());
    cnt1 = cnt2 = 0;
    dijkstra<G>(gg, d, a * (m + 1));
    cerr << cnt1 << ' ' << cnt2 << endl;
    int mc = INF;
    REP(i, m + 1) mc = min(mc, d[h * (m + 1) + i]);
    if (mc < INF)
      cout << mc << endl;
    else
      cout << "Help!" << endl;
  }
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>

using namespace std;

#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
typedef int Weight;
typedef pair<Weight, int> Data;
// enable reduce
struct Heap {
  shared_ptr<Heap> l, r, p;
  Data val;
  Heap(Data v) : val(v) {}
  Data top() { return val; }
};
int cnt1, cnt2;
shared_ptr<Heap> meld(shared_ptr<Heap> a, shared_ptr<Heap> b,
                      shared_ptr<Heap> p = nullptr) {
  ++cnt1;
  if (p == nullptr)
    ++cnt2;
  if (!a) {
    if (b)
      b->p = p;
    return b;
  }
  if (!b) {
    if (a)
      a->p = p;
    return a;
  }
  if (a->val > b->val)
    swap(a, b);
  a->p = p;
  a->r = meld(a->r, b, a);
  swap(a->l, a->r);
  return a;
}
pair<shared_ptr<Heap>, shared_ptr<Heap>> push(shared_ptr<Heap> h, Data v) {
  auto n = make_shared<Heap>(v);
  return make_pair(meld(h, n), n);
}
shared_ptr<Heap> pop(shared_ptr<Heap> h) {
  if (h->l)
    h->l->p.reset();
  if (h->r)
    h->r->p.reset();
  return meld(h->l, h->r);
}
shared_ptr<Heap> reduce(shared_ptr<Heap> h, shared_ptr<Heap> root, Data v) {
  if (v > h->val)
    return root;
  h->val = v;
  if (!h->p)
    return root;
  if (h->val < h->p->val) {
    if (h->p->l && h->p->l == h) {
      h->p->l.reset();
      return meld(h, root);
    } else {
      h->p->r.reset();
      return meld(h, root);
    }
  } else
    return root;
}

Weight INF = 1000000000;
struct Edge {
  int src, dest;
  Weight weight;
  bool operator<(const Edge &rhs) const { return weight > rhs.weight; }
};

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void add_edge(Graph &g, int src, int dest, Weight weight) {
  g[src].push_back((Edge){src, dest, weight});
  g[dest].push_back((Edge){dest, src, weight});
}

template <typename G> void dijkstra(G &g, Array &d, int s) {
  int n = g.size();
  d.assign(n, INF);
  d[s] = 0;
  shared_ptr<Heap> que;
  vector<shared_ptr<Heap>> nodes(n);
  auto p = push(que, Data(0, s));
  que = p.first;
  nodes[s] = p.second;
  assert(que != nullptr);
  while (que) {
    Weight dist = que->top().first;
    int v = que->top().second;
    que = pop(que);
    nodes[v].reset();
    if (d[v] < dist)
      continue;
    REP(i, g(v).size()) {
      Edge e = g(v)[i];
      if (d[e.dest] > d[v] + e.weight) {
        d[e.dest] = d[v] + e.weight;
        if (!nodes[e.dest]) {
          auto p = push(que, Data(d[e.dest], e.dest));
          que = p.first;
          nodes[e.dest] = p.second;
        } else {
          que = reduce(nodes[e.dest], que, Data(d[e.dest], e.dest));
        }
      }
    }
  }
}

struct G {
  Graph g;
  int m;
  vector<bool> f;
  G(Graph &g, int m, vector<bool> &f) : g(g), m(m), f(f) {}
  Edges operator()(int i) {
    int j = i / (m + 1);
    int k = i % (m + 1);
    Edges es;
    REP(l, g[j].size()) {
      if (k + g[j][l].weight > m)
        continue;
      es.push_back((Edge){i, g[j][l].dest * (m + 1) + k + g[j][l].weight,
                          g[j][l].weight});
    }
    if (f[j] && k)
      es.push_back((Edge){i, i - 1, 1});
    return es;
  }
  size_t size() const { return g.size() * (m + 1); }
};

int main() {
  while (1) {
    int n, m, l, k, a, h;
    cin >> n >> m >> l >> k >> a >> h;
    if (!n)
      break;
    vector<int> f(l);
    REP(i, l) cin >> f[i];
    Graph g(n);
    REP(i, k) {
      int s, t, c;
      cin >> s >> t >> c;
      add_edge(g, s, t, c);
    }
    vector<bool> fb(n, false);
    REP(i, l) fb[f[i]] = true;
    G gg(g, m, fb);
    Array d(gg.size());
    cnt1 = cnt2 = 0;
    dijkstra<G>(gg, d, a * (m + 1));
    int mc = INF;
    REP(i, m + 1) mc = min(mc, d[h * (m + 1) + i]);
    if (mc < INF)
      cout << mc << endl;
    else
      cout << "Help!" << endl;
  }
  return 0;
}