Problem p00962 (C++) — buggy submission, verdict: Runtime Error

#include <cassert>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <vector>

#define show(x) cerr << #x << " = " << x << endl

using namespace std;
using ll = long long;

constexpr ll INF = numeric_limits<ll>::max() / 16;

template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "sz:" << v.size() << "\\n[";
  for (const auto &p : v) {
    os << p << ",";
  }
  os << "]\\n";
  return os;
}

struct CostGraph {
  using T = ll;
  CostGraph(const int v) : V{v} {
    edge.resize(v);
    rev_edge.resize(v);
  }
  struct Edge {
    Edge() {}
    Edge(const int from, const int to, const T cost)
        : from{from}, to{to}, cost{cost} {}
    int from;
    int to;
    T cost;
    bool operator<(const Edge &e) const {
      return cost != e.cost ? cost < e.cost : to < e.to;
    }
  };
  void addEdge(const int from, const int to, const T cost) {
    edge[from].push_back(Edge{from, to, cost});
    rev_edge[to].push_back(Edge{to, from, cost});
  }
  vector<vector<Edge>> edge;
  vector<vector<Edge>> rev_edge;
  const int V;
};

ostream &operator<<(ostream &os, const CostGraph::Edge &e) {
  os << "(" << e.from << "->" << e.to << ": " << e.cost << ")" << endl;
  return os;
}

void Dijkstra(const CostGraph &g, const int s, vector<CostGraph::T> &d) {
  using T = CostGraph::T;
  assert(s < g.V);
  assert(d.size() == g.V);
  using P = pair<T, int>;
  priority_queue<P, vector<P>, greater<P>> q;
  for (int i = 0; i < g.V; i++) {
    d[i] = INF;
  }
  d[s] = 0;
  q.push(make_pair(0, s));
  while (not q.empty()) {
    const P &p = q.top();
    const T cost = p.first;
    const int v = p.second;
    q.pop();
    if (d[v] < cost) {
      continue;
    }
    for (const auto &e : g.edge[v]) {
      if (d[e.to] > d[v] + e.cost) {
        d[e.to] = d[v] + e.cost;
        q.push(make_pair(d[e.to], e.to));
      }
    }
  }
}
void ReverseDijkstra(const CostGraph &g, const int s, vector<CostGraph::T> &d) {
  using T = CostGraph::T;
  assert(s < g.V);
  assert(d.size() == g.V);
  using P = pair<T, int>;
  priority_queue<P, vector<P>, greater<P>> q;
  for (int i = 0; i < g.V; i++) {
    d[i] = INF;
  }
  d[s] = 0;
  q.push(make_pair(0, s));
  while (not q.empty()) {
    const P &p = q.top();
    const T cost = p.first;
    const int v = p.second;
    q.pop();
    if (d[v] < cost) {
      continue;
    }
    for (const auto &e : g.rev_edge[v]) {
      if (d[e.to] > d[v] + e.cost) {
        d[e.to] = d[v] + e.cost;
        q.push(make_pair(d[e.to], e.to));
      }
    }
  }
}

struct BiconnectedComponent {
public:
  BiconnectedComponent(const CostGraph &g_)
      : num{0}, comp_num{0}, size{g_.V}, bridge(0), ord(size, -1), low(size, 0),
        comp(size, -1) {
    for (int i = 0; i < size; i++) {
      bridge_dfs(g_, i);
    }
    for (int i = 0; i < size; i++) {
      if (comp[i] >= 0) {
        continue;
      }
      comp_dfs(g_, i, comp_num);
      comp_num++;
    }
  }

  CostGraph toTree() const {
    CostGraph tree(comp_num);
    for (const auto &e : bridge) {
      tree.addEdge(comp[e.from], comp[e.to], 1);
      tree.addEdge(comp[e.to], comp[e.from], 1);
    }
    return tree;
  }
  const vector<CostGraph::Edge> &getEdge() const { return bridge; }
  bool isBridge(const int i, const int j) const {
    return (ord[i] < ord[j]) ? ord[i] < low[j] : ord[j] < low[i];
  }
  const vector<int> &getComp() const { return comp; }

  void bridge_dfs(const CostGraph &g_, const int s, const int par = -1) {
    ord[s] = num;
    low[s] = num;
    num++;
    for (const auto &e : g_.edge[s]) {
      const int to = e.to;
      if (to == par) {
        continue;
      }
      if (ord[to] >= 0) {
        low[s] = min(low[s], ord[to]);
      } else {
        bridge_dfs(g_, to, s);
        low[s] = min(low[s], low[to]);
      }
      if (isBridge(s, to)) {
        bridge.push_back(e);
      }
    }
  }

  void comp_dfs(const CostGraph &g_, const int s, const int c) {
    comp[s] = c;
    for (const auto &e : g_.edge[s]) {
      const int to = e.to;
      if ((comp[to] == -1) and (not isBridge(s, to))) {
        comp_dfs(g_, to, c);
      }
    }
  }
  int num;
  int comp_num;
  const int size;
  vector<CostGraph::Edge> bridge;
  vector<int> ord;
  vector<int> low;
  vector<int> comp;
};

int main() {
  int n, m;
  cin >> n >> m;

  CostGraph g(n);
  using E = tuple<int, int, ll>;
  vector<E> edge(m);
  for (int i = 0; i < m; i++) {
    int a, b;
    ll c;
    cin >> a >> b >> c;
    a--, b--;
    g.addEdge(a, b, c);
    edge[i] = make_tuple(a, b, c);
  }
  vector<ll> ds(n, INF);
  Dijkstra(g, 0, ds);
  vector<ll> dt(n, INF);
  ReverseDijkstra(g, 1, dt);
  const ll D = ds[1];
  CostGraph undg(n);
  for (int i = 0; i < m; i++) {
    const E e = edge[i];
    const int u = get<0>(e);
    const int v = get<1>(e);
    const ll c = get<2>(e);
    if (ds[u] + c + dt[v] == D) {
      undg.addEdge(u, v, c);
      undg.addEdge(v, u, c);
    }
  }

  using pii = pair<int, int>;
  BiconnectedComponent bic(undg);
  set<E> bridge;
  for (const auto &e : bic.bridge) {
    const int u = e.from;
    const int v = e.to;
    bridge.insert(make_tuple(u, v, e.cost));
  }
  for (int i = 0; i < m; i++) {
    const E e = edge[i];
    const int u = get<0>(e);
    const int v = get<1>(e);
    const ll c = get<2>(e);
    if (ds[v] + c + dt[u] < D) {
      cout << "HAPPY" << endl;
    } else {
      if (not(bridge.find(make_tuple(u, v, c)) == bridge.end() and
              bridge.find(make_tuple(v, u, c)) == bridge.end())) {
        cout << "SAD" << endl;
      } else {
        cout << "SOSO" << endl;
      }
    }
  }
  return 0;
}

Error: 0
ds = sz:4
[0,18,5,11,]

dt = sz:4
[18,0,13,7,]

bic.bridge = sz:3
[(3->1: 7)
,(2->3: 6)
,(0->2: 5)
,]



Fixed submission:

#include <cassert>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <vector>

#define show(x) cerr << #x << " = " << x << endl

using namespace std;
using ll = long long;

constexpr ll INF = numeric_limits<ll>::max() / 16;

template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "sz:" << v.size() << "\\n[";
  for (const auto &p : v) {
    os << p << ",";
  }
  os << "]\\n";
  return os;
}

struct CostGraph {
  using T = ll;
  CostGraph(const int v) : V{v} {
    edge.resize(v);
    rev_edge.resize(v);
  }
  struct Edge {
    Edge() {}
    Edge(const int from, const int to, const T cost)
        : from{from}, to{to}, cost{cost} {}
    int from;
    int to;
    T cost;
    bool operator<(const Edge &e) const {
      return cost != e.cost ? cost < e.cost : to < e.to;
    }
  };
  void addEdge(const int from, const int to, const T cost) {
    edge[from].push_back(Edge{from, to, cost});
    rev_edge[to].push_back(Edge{to, from, cost});
  }
  vector<vector<Edge>> edge;
  vector<vector<Edge>> rev_edge;
  const int V;
};

ostream &operator<<(ostream &os, const CostGraph::Edge &e) {
  os << "(" << e.from << "->" << e.to << ": " << e.cost << ")" << endl;
  return os;
}

void Dijkstra(const CostGraph &g, const int s, vector<CostGraph::T> &d) {
  using T = CostGraph::T;
  assert(s < g.V);
  assert(d.size() == g.V);
  using P = pair<T, int>;
  priority_queue<P, vector<P>, greater<P>> q;
  for (int i = 0; i < g.V; i++) {
    d[i] = INF;
  }
  d[s] = 0;
  q.push(make_pair(0, s));
  while (not q.empty()) {
    const P &p = q.top();
    const T cost = p.first;
    const int v = p.second;
    q.pop();
    if (d[v] < cost) {
      continue;
    }
    for (const auto &e : g.edge[v]) {
      if (d[e.to] > d[v] + e.cost) {
        d[e.to] = d[v] + e.cost;
        q.push(make_pair(d[e.to], e.to));
      }
    }
  }
}
void ReverseDijkstra(const CostGraph &g, const int s, vector<CostGraph::T> &d) {
  using T = CostGraph::T;
  assert(s < g.V);
  assert(d.size() == g.V);
  using P = pair<T, int>;
  priority_queue<P, vector<P>, greater<P>> q;
  for (int i = 0; i < g.V; i++) {
    d[i] = INF;
  }
  d[s] = 0;
  q.push(make_pair(0, s));
  while (not q.empty()) {
    const P &p = q.top();
    const T cost = p.first;
    const int v = p.second;
    q.pop();
    if (d[v] < cost) {
      continue;
    }
    for (const auto &e : g.rev_edge[v]) {
      if (d[e.to] > d[v] + e.cost) {
        d[e.to] = d[v] + e.cost;
        q.push(make_pair(d[e.to], e.to));
      }
    }
  }
}

struct BiconnectedComponent {
public:
  BiconnectedComponent(const CostGraph &g_)
      : num{0}, comp_num{0}, size{g_.V}, bridge(0), ord(size, -1), low(size, 0),
        comp(size, -1) {
    for (int i = 0; i < size; i++) {
      bridge_dfs(g_, i);
    }
    for (int i = 0; i < size; i++) {
      if (comp[i] >= 0) {
        continue;
      }
      comp_dfs(g_, i, comp_num);
      comp_num++;
    }
  }

  CostGraph toTree() const {
    CostGraph tree(comp_num);
    for (const auto &e : bridge) {
      tree.addEdge(comp[e.from], comp[e.to], 1);
      tree.addEdge(comp[e.to], comp[e.from], 1);
    }
    return tree;
  }
  const vector<CostGraph::Edge> &getEdge() const { return bridge; }
  bool isBridge(const int i, const int j) const {
    return (ord[i] < ord[j]) ? ord[i] < low[j] : ord[j] < low[i];
  }
  const vector<int> &getComp() const { return comp; }

  void bridge_dfs(const CostGraph &g_, const int s, const int par = -1) {
    ord[s] = num;
    low[s] = num;
    num++;
    for (const auto &e : g_.edge[s]) {
      const int to = e.to;
      if (to == par) {
        continue;
      }
      if (ord[to] >= 0) {
        low[s] = min(low[s], ord[to]);
      } else {
        bridge_dfs(g_, to, s);
        low[s] = min(low[s], low[to]);
      }
      if (isBridge(s, to)) {
        bridge.push_back(e);
      }
    }
  }

  void comp_dfs(const CostGraph &g_, const int s, const int c) {
    comp[s] = c;
    for (const auto &e : g_.edge[s]) {
      const int to = e.to;
      if ((comp[to] == -1) and (not isBridge(s, to))) {
        comp_dfs(g_, to, c);
      }
    }
  }
  int num;
  int comp_num;
  const int size;
  vector<CostGraph::Edge> bridge;
  vector<int> ord;
  vector<int> low;
  vector<int> comp;
};

int main() {
  int n, m;
  cin >> n >> m;

  CostGraph g(n);
  using E = tuple<int, int, ll>;
  vector<E> edge(m);
  for (int i = 0; i < m; i++) {
    int a, b;
    ll c;
    cin >> a >> b >> c;
    a--, b--;
    g.addEdge(a, b, c);
    edge[i] = make_tuple(a, b, c);
  }
  vector<ll> ds(n, INF);
  Dijkstra(g, 0, ds);
  vector<ll> dt(n, INF);
  ReverseDijkstra(g, 1, dt);
  show(ds);
  show(dt);
  const ll D = ds[1];
  CostGraph undg(n);
  for (int i = 0; i < m; i++) {
    const E e = edge[i];
    const int u = get<0>(e);
    const int v = get<1>(e);
    const ll c = get<2>(e);
    if (ds[u] + c + dt[v] == D) {
      undg.addEdge(u, v, c);
      undg.addEdge(v, u, c);
    }
  }

  using pii = pair<int, int>;
  BiconnectedComponent bic(undg);
  show(bic.bridge);
  set<E> bridge;
  for (const auto &e : bic.bridge) {
    const int u = e.from;
    const int v = e.to;
    bridge.insert(make_tuple(u, v, e.cost));
  }
  for (int i = 0; i < m; i++) {
    const E e = edge[i];
    const int u = get<0>(e);
    const int v = get<1>(e);
    const ll c = get<2>(e);
    if (ds[v] + c + dt[u] < D) {
      cout << "HAPPY" << endl;
    } else {
      if (not(bridge.find(make_tuple(u, v, c)) == bridge.end() and
              bridge.find(make_tuple(v, u, c)) == bridge.end())) {
        cout << "SAD" << endl;
      } else {
        cout << "SOSO" << endl;
      }
    }
  }
  return 0;
}