#include <bits/stdc++.h>
using namespace std;
using uint = unsigned int;
using lint = long long int;
using ulint = unsigned long long int;
template<class T = int> using V = vector<T>;
template<class T = int> using VV = V< V<T> >;
template<class T, class U> void assign(V<T>& v, int n, const U& a) { v.assign(n, a); }
template<class T, class... Args> void assign(V<T>& v, int n, const Args&... args) { v.resize(n); for (auto&& e : v) assign(e, args...); }


struct AdditiveGroup {
  using T = lint;
  static T op(const T& lhs, const T& rhs) { return lhs + rhs; }
  static constexpr T e() { return 0; }
  static T inv(const T& val) { return -val; }
};

template<class AbelianGroup> struct UnionFind {
  using AG = AbelianGroup;
  using T = typename AG::T;

  V<> dat;
  V<T> pot;

  UnionFind(int n) : dat(n, -1), pot(n, AG::e()) {}

  T sub(const T& lhs, const T& rhs) { return AG::op(lhs, AG::inv(rhs)); }

  T diff(int u, int v) {
    assert(same(u, v));
    return sub(pot[v], pot[u]);
  }

  int find(int v) {
    if (dat[v] < 0) return v;
    else {
      int r = find(dat[v]);
      pot[v] = AG::op(pot[v], pot[dat[v]]);
      return dat[v] = r;
    }
  }

  bool same(int u, int v) { return find(u) == find(v); }

  int size(int v) { return -dat[find(v)]; }

  void unite(int u, int v, T d) {
    assert(!same(u, v));
    d = sub(d, sub(pot[v], pot[u]));
    if (dat[u] >= 0) u = dat[u];
    if (dat[v] >= 0) v = dat[v];
    if (-dat[u] < -dat[v]) {
      dat[v] += dat[u];
      dat[u] = v;
      pot[u] = AG::inv(d);
    } else {
      dat[u] += dat[v];
      dat[v] = u;
      pot[v] = d;
    }
  }
};

int main() {
  cin.tie(nullptr); ios_base::sync_with_stdio(false);
  int R, C, n; cin >> R >> C >> n;
  struct S { int r, c; lint a; };
  VV<S> row(R), col(C);
  for (int i = 0; i < n; ++i) {
    int r, c, a; cin >> r >> c >> a, --r, --c;
    row[r].push_back({r, c, a});
    col[c].push_back({r, c, a});
  }
  UnionFind<AdditiveGroup> ufc(C), ufr(R);
  for (int r = 0; r < R; ++r) {
    int m = row[r].size();
    for (int i = 0; i < m - 1; ++i) {
      if (ufc.same(row[r][i].c, row[r][i + 1].c)) {
        if (ufc.diff(row[r][i].c, row[r][i + 1].c) != row[r][i + 1].a - row[r][i].a) return cout << "No" << '\n', 0;
      } else {
        ufc.unite(row[r][i].c, row[r][i + 1].c, row[r][i + 1].a - row[r][i].a);
      }
    }
  }
  for (int c = 0; c < C; ++c) {
    int m = col[c].size();
    for (int i = 0; i < m - 1; ++i) {
      if (ufr.same(col[c][i].r, col[c][i + 1].r)) {
        if (ufr.diff(col[c][i].r, col[c][i + 1].r) != col[c][i + 1].a - col[c][i].a) return cout << "No" << '\n', 0;
      } else {
        ufr.unite(col[c][i].r, col[c][i + 1].r, col[c][i + 1].a - col[c][i].a);
      }
    }
  }
  bitset<200'000> vis;
  V<lint> x(R + C);
  for (int i = 0; i < R + C; ++i) if (!vis[i]) {
    lint mnr = 1e12, mnc = 1e12;
    queue<int> que;
    vis[i] = true;
    (i < R ? mnr : mnc) = 0;
    que.push(i);
    while (!que.empty()) {
      int j = que.front(); que.pop();
      if (j < R) {
        for (const auto& e : row[j]) if (!vis[R + e.c]) {
          vis[R + e.c] = true;
          mnc = min(mnc, x[R + e.c] = e.a - x[j]);
          que.push(R + e.c);
        }
      } else {
        for (const auto& e : col[j - R]) if (!vis[e.r]) {
          vis[e.r] = true;
          mnr = min(mnr, x[e.r] = e.a - x[j]);
          que.push(e.r);
        }
      }
    }
    if (mnr + mnc < 0) return cout << "No" << '\n', 0;
  }
  cout << "Yes" << '\n';
}

Measured memory_bytes: 15104