Problem p03995 (C++)

Buggy submission (status: Runtime Error):
#include <iostream>
#include <numeric>
#include <tuple>
#include <vector>

template <class Dist> struct WeightedUnionFind {
  std::vector<int> par, sz;
  std::vector<Dist> dist; // A[par[v]] - A[v] = dist[v]
  int gnum;

  explicit WeightedUnionFind(int n) : par(n), sz(n, 1), dist(n, 0), gnum(n) {
    std::iota(par.begin(), par.end(), 0);
  }

  int find(int v) {
    if (par[v] == v) {
      return v;
    } else {
      int p = find(par[v]);
      dist[v] += dist[par[v]];
      return par[v] = p;
    }
  }

  // A[u] - A[v] = d
  void unite(int u, int v, Dist d) {
    find(u), find(v);
    d += dist[u];
    d -= dist[v];
    u = par[u], v = par[v];
    if (u == v)
      return;

    if (sz[u] < sz[v]) {
      std::swap(u, v);
      d = -d;
    }

    sz[u] += sz[v];
    par[v] = u;
    dist[v] = d;
    --gnum;
  }

  // A[u] - A[v]
  Dist diff(int u, int v) {
    find(u), find(v);
    return dist[v] - dist[u];
  }

  bool same(int u, int v) { return find(u) == find(v); }
  bool ispar(int v) { return v == find(v); }
  int size(int v) { return sz[find(v)]; }
};

void solve() {
  int h, w, n;
  std::cin >> h >> w >> n;

  std::vector<std::vector<std::pair<int, int>>> gs(n);
  while (n--) {
    int x, y, v;
    std::cin >> x >> y >> v;
    --x, --y;
    gs[x].emplace_back(y, v);
  }

  WeightedUnionFind<int> wuf(w);
  for (const auto &g : gs) {
    int m = g.size();
    for (int i = 0; i + 1 < m; ++i) {
      int u = g[i].first, v = g[i + 1].first;
      int d = g[i].second - g[i + 1].second;

      if (wuf.same(u, v)) {
        if (wuf.diff(u, v) != d) {
          std::cout << "No" << std::endl;
          return;
        }
      } else {
        wuf.unite(u, v, d);
      }
    }
  }

  std::vector<int> minidx(w);
  std::iota(minidx.begin(), minidx.end(), 0);
  for (int v = 0; v < w; ++v) {
    int p = wuf.find(v);
    if (wuf.diff(v, p) < wuf.diff(minidx[p], p)) {
      minidx[p] = v;
    }
  }

  for (const auto &g : gs) {
    for (auto t : g) {
      int y, v;
      std::tie(y, v) = t;

      int p = wuf.find(y);
      v -= wuf.diff(y, minidx[p]);

      if (v < 0) {
        std::cout << "No" << std::endl;
        return;
      }
    }
  }

  std::cout << "Yes" << std::endl;
  return;
}

int main() {
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);
  std::ios::sync_with_stdio(false);

  solve();

  return 0;
}


Fixed submission:
#include <iostream>
#include <numeric>
#include <tuple>
#include <vector>

template <class Dist> struct WeightedUnionFind {
  std::vector<int> par, sz;
  std::vector<Dist> dist; // A[par[v]] - A[v] = dist[v]
  int gnum;

  explicit WeightedUnionFind(int n) : par(n), sz(n, 1), dist(n, 0), gnum(n) {
    std::iota(par.begin(), par.end(), 0);
  }

  int find(int v) {
    if (par[v] == v) {
      return v;
    } else {
      int p = find(par[v]);
      dist[v] += dist[par[v]];
      return par[v] = p;
    }
  }

  // A[u] - A[v] = d
  void unite(int u, int v, Dist d) {
    find(u), find(v);
    d += dist[u];
    d -= dist[v];
    u = par[u], v = par[v];
    if (u == v)
      return;

    if (sz[u] < sz[v]) {
      std::swap(u, v);
      d = -d;
    }

    sz[u] += sz[v];
    par[v] = u;
    dist[v] = d;
    --gnum;
  }

  // A[u] - A[v]
  Dist diff(int u, int v) {
    find(u), find(v);
    return dist[v] - dist[u];
  }

  bool same(int u, int v) { return find(u) == find(v); }
  bool ispar(int v) { return v == find(v); }
  int size(int v) { return sz[find(v)]; }
};

void solve() {
  int h, w, n;
  std::cin >> h >> w >> n;

  std::vector<std::vector<std::pair<int, int>>> gs(h);
  while (n--) {
    int x, y, v;
    std::cin >> x >> y >> v;
    --x, --y;
    gs[x].emplace_back(y, v);
  }

  WeightedUnionFind<int> wuf(w);
  for (const auto &g : gs) {
    int m = g.size();
    for (int i = 0; i + 1 < m; ++i) {
      int u = g[i].first, v = g[i + 1].first;
      int d = g[i].second - g[i + 1].second;

      if (wuf.same(u, v)) {
        if (wuf.diff(u, v) != d) {
          std::cout << "No" << std::endl;
          return;
        }
      } else {
        wuf.unite(u, v, d);
      }
    }
  }

  std::vector<int> minidx(w);
  std::iota(minidx.begin(), minidx.end(), 0);
  for (int v = 0; v < w; ++v) {
    int p = wuf.find(v);
    if (wuf.diff(v, p) < wuf.diff(minidx[p], p)) {
      minidx[p] = v;
    }
  }

  for (const auto &g : gs) {
    for (auto t : g) {
      int y, v;
      std::tie(y, v) = t;

      int p = wuf.find(y);
      v -= wuf.diff(y, minidx[p]);

      if (v < 0) {
        std::cout << "No" << std::endl;
        return;
      }
    }
  }

  std::cout << "Yes" << std::endl;
  return;
}

int main() {
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);
  std::ios::sync_with_stdio(false);

  solve();

  return 0;
}