import std.stdio, std.string, std.conv;
import std.range, std.algorithm, std.array;

void main() {
    int n, m;
    scan(n, m);

    auto uf = WeightedUnionFind!(int)(n + 1);
    bool ok = 1;

    foreach (i ; 0 .. m) {
        int l, r, d;
        scan(l, r, d);

        if (uf.same(l, r)) {
            if (uf.diff(l, r) != d) {
                ok = 0;
            }
        }
        else {
            uf.merge(l, r, d);
        }
    }

    writeln(ok ? "Yes" : "No");
}



struct WeightedUnionFind(T) {
    private {
        int[] _parent, _rank;
        T[] _diff;
    }

    this(int N) {
        _parent = new int[](N);
        _rank = new int[](N);
        _diff = new T[](N);

        foreach (i ; 0 .. N) {
            _parent[i] = i;
        }
    }

    int findRoot(int x) {
        if (_parent[x] != x) {
            int r = findRoot(_parent[x]);
            _diff[x] += _diff[_parent[x]];
            _parent[x] = findRoot(r);
        }

        return _parent[x];
    }

    bool same(int x, int y) {
        return findRoot(x) == findRoot(y);
    }

    T weight(int x) {
        findRoot(x);
        return _diff[x];
    }

    // x と y が異なるグループに属すならinf(十分大きい値)を返す
    T diff(int x, int y) {
        return same(x, y) ? weight(y) - weight(x) : T.max;
    }

    import std.algorithm : swap;

    // weight(y) = weight(x) + w
    bool merge(int x, int y, T w) {
        w += weight(x) - weight(y);

        int u = findRoot(x);
        int v = findRoot(y);

        // x と y　が既に同じグループであるなら距離の更新はしない
        if (u == v) return false;

        if (_rank[u] < _rank[v]) {
            swap(u, v);
            w = -w;
        }

        if (_rank[u] == _rank[v]) {
            _rank[u]++;
        }

        _parent[v] = u;
        _diff[v] = w;

        return true;
    }
}





void scan(T...)(ref T args) {
    import std.stdio : readln;
    import std.algorithm : splitter;
    import std.conv : to;
    import std.range.primitives;

    auto line = readln().splitter();
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront();
    }
    assert(line.empty);
}



void fillAll(R, T)(ref R arr, T value) {
    static if (is(typeof(arr[] = value))) {
        arr[] = value;
    }
    else {
        foreach (ref e; arr) {
            fillAll(e, value);
        }
    }
}
