#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<long long, long long>;
#define rep(i, n) for(int i = 0; i < (n); ++i)
#define all(x) (x).begin(),(x).end()
constexpr char ln = '\n';
constexpr long long MOD = 1000000007;
//constexpr long long MOD = 998244353;
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) { if (a < b) { a = b; return true;} return false; }
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) { if (a > b) { a = b; return true;} return false; }
inline int popcount(int x) {return __builtin_popcount(x);}
inline int popcount(long long x) {return __builtin_popcountll(x);}
void print() { cout << "\n"; }
template<class T, class... Args>
void print(const T &x, const Args &... args) {
    cout << x << " ";
    print(args...);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

void No() {
    cout << "No" << ln;
    exit(0);
}

template<class Abel> struct WeightedUnionFind {
    vector<int> par;
    vector<int> rank;
    vector<Abel> diff_weight;

    WeightedUnionFind(int n = 1, Abel SUM_UNITY = 0) {
        init(n, SUM_UNITY);
    }

    void init(int n = 1, Abel SUM_UNITY = 0) {
        par.resize(n); rank.resize(n); diff_weight.resize(n);
        for (int i = 0; i < n; ++i) par[i] = i, rank[i] = 0, diff_weight[i] = SUM_UNITY;
    }

    int root(int x) {
        if (par[x] == x) {
            return x;
        }
        else {
            int r = root(par[x]);
            diff_weight[x] += diff_weight[par[x]];
            return par[x] = r;
        }
    }

    Abel weight(int x) {
        root(x);
        return diff_weight[x];
    }

    bool issame(int x, int y) {
        return root(x) == root(y);
    }

    bool merge(int x, int y, Abel w) {
        w += weight(x); w -= weight(y);
        x = root(x); y = root(y);
        if (x == y) return false;
        if (rank[x] < rank[y]) swap(x, y), w = -w;
        if (rank[x] == rank[y]) ++rank[x];
        par[y] = x;
        diff_weight[y] = w;
        return true;
    }

    Abel diff(int x, int y) {
        return weight(y) - weight(x);
    }
};

const ll INF = 1e18;
using Tu = tuple<int, int, ll>;
int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);
    int H,W; cin >> H >> W;
    int N; cin >> N;
    vector<vector<pll>> R(H),C(W);
    vector<Tu> A(N);
    rep(i,N) {
        int h,w,a; cin >> h >> w >> a;
        --h; --w;
        R[h].emplace_back(w,a);
        C[w].emplace_back(h,a);
        A[i] = Tu(h,w,a);
    } 

    WeightedUnionFind<ll> ufr(H),ufw(W);
    rep(i,H) {
        int K = R[i].size();
        rep(j,K-1) {
            auto[w1,a1] = R[i][j];
            auto[w2,a2] = R[i][j+1];
            if (ufw.issame(w1,w2)) {
                if (a1+ufw.diff(w1,w2)!=a2) No();
            } else {
                ufw.merge(w1,w2,a2-a1);
            }
        }
    }
    rep(i,W) {
        int K = C[i].size();
        rep(j,K-1) {
            auto[h1,a1] = C[i][j];
            auto[h2,a2] = C[i][j+1];
            if (ufr.issame(h1,h2)) {
                if (a1+ufr.diff(h1,h2)!=a2) No();
            } else {
                ufr.merge(h1,h2,a2-a1);
            }
        }
    }

    vector<ll> lh(H),lw(W);
    rep(i,H) chmin(lh[ufr.root(i)],ufr.weight(i));
    rep(i,W) chmin(lw[ufw.root(i)],ufw.weight(i));
    rep(i,H) lh[i] = lh[ufr.root(i)];
    rep(i,W) lw[i] = lw[ufw.root(i)];
    rep(i,N) {
        auto[h,w,a] = A[i];
        ll diffh = ufr.weight(h) - lh[h];
        if (a < diffh) No();
        ll diffw = ufw.weight(w) - lw[w];
        if (a < diffw) No();
    }

    cout << "Yes" << ln;
}


Measured memory_bytes: 20352