#include <algorithm>
#include <cassert>
#include <cmath>
#include <deque>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

using namespace std;

constexpr int NIL = numeric_limits<int>::min();

struct Info {
    int L, R, D;
};

struct CompareL {
    bool operator()(const Info& lhs, const Info& rhs) const {
        return make_pair(lhs.L, lhs.R) < make_pair(rhs.L, rhs.R);
    }
};

struct CompareR {
    bool operator()(const Info& lhs, const Info& rhs) const {
        return make_pair(lhs.R, lhs.L) < make_pair(rhs.R, rhs.L);
    }
};

int main()
{
    int N;
    int M;
    cin >> N >> M;

    vector<Info> infosL(M);
    for (int i = 0; i < M; ++i) {
        cin >> infosL[i].L >> infosL[i].R >> infosL[i].D;
        --infosL[i].L;
        --infosL[i].R;
    }

    vector<Info> infosR = infosL;

    sort(infosL.begin(), infosL.end(), CompareL());
    sort(infosR.begin(), infosR.end(), CompareR());

    vector<int> pos(N, NIL);
    set<int> undet;
    for (int i = 0; i < N; ++i)
        undet.insert(i);

    while (!undet.empty()) {
        int i = *undet.begin();
        assert(pos[i] == NIL);
        pos[i] = 0;
        undet.erase(i);

        deque<Info> q;
        auto beginL = lower_bound(infosL.begin(), infosL.end(), Info{i, 0, 0},
                                  CompareL());
        auto endL = lower_bound(infosL.begin(), infosL.end(), Info{i + 1, 0, 0},
                                CompareL());
        auto beginR = lower_bound(infosR.begin(), infosR.end(), Info{0, i, 0},
                                  CompareR());
        auto endR = lower_bound(infosR.begin(), infosR.end(), Info{0, i + 1, 0},
                                CompareR());

        q.insert(q.end(), beginL, endL);
        q.insert(q.end(), beginR, endR);

        while (!q.empty()) {
            Info info = q.front();
            q.pop_front();

            assert(pos[info.L] != NIL || pos[info.R] != NIL);

            int det = -1;
            if (pos[info.L] != NIL && pos[info.R] != NIL) {
                if (pos[info.R] - pos[info.L] != info.D) {
                    cout << "No\n";
                    return 0;
                }
            } else if (pos[info.L] != NIL) {
                pos[info.R] = pos[info.L] + info.D;
                det = info.R;
            } else if (pos[info.R] != NIL) {
                pos[info.L] = pos[info.R] - info.D;
                det = info.L;
            }

            if (det == -1)
                continue;

            undet.erase(det);

            beginL = lower_bound(infosL.begin(), infosL.end(), Info{det, 0, 0},
                                 CompareL());
            endL = lower_bound(infosL.begin(), infosL.end(), Info{det + 1, 0, 0},
                               CompareL());
            beginR = lower_bound(infosR.begin(), infosR.end(), Info{0, det, 0},
                                 CompareR());
            endR = lower_bound(infosR.begin(), infosR.end(), Info{0, det + 1, 0},
                               CompareR());

            q.insert(q.end(), beginL, endL);
            q.insert(q.end(), beginR, endR);
        }
    }

    cout << "Yes\n";

    return 0;
}


Measured memory_bytes: 12032