/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author JustLive
 */

#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define ford(i, n) for (int i = (int)(n) - 1; i >= 0; --i)
#define fore(i, a, b) for (int i = (int)(a); i <= (int)(b); ++i)
#define forr(i, a, b) for (int i = (int)(a); i >= (int)(b); --i)

#ifdef LOCAL_SYSTEM
#define DEBUG(x) cerr << #x << ": " << (x) << endl;
#define DEBUGARR(a, n) cerr << #a << ": "; print_array(cerr, a, n); cerr << endl;
#else
#define DEBUG(x)
#define DEBUGARR(a, n)
#endif

using namespace std;

template<typename T> void print_sequential_container(ostream& stream, const vector<T>& c) {
    stream << "[";
    auto &last = *(--c.end());
    for (auto &e: c) {
        stream << e;
        if (e != last) {
            stream << ", ";
        }
    }
    stream << "]";
}

template<typename T> void print_array(ostream& stream, T a[], int n) {
    stream << "[";
    for (int i = 0; i < n; i++) {
        stream << a[i];
        if (i != n - 1) {
            stream << ", ";
        }
    }
    stream << "]";
}

template<typename T> void print_set(ostream& stream, const T& c) {
    stream << "{";
    auto &last = *(--c.end());
    for (auto &e: c) {
        stream << e;
        if (e != last) {
            stream << ", ";
        }
    }
    stream << "}";
}

template<typename T> void print_map(ostream& stream, const T& c) {
    stream << "{";
    auto &last = *(--c.end());
    for (auto &e: c) {
        stream << e.fi << ": " << e.se;
        if (e != last) {
            stream << ", ";
        }
    }
    stream << "}";
}

template<typename T> ostream& operator << (ostream& stream, const vector<T>& c) {
    print_sequential_container(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const list<T>& c) {
    print_sequential_container(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const forward_list<T>& c) {
    print_sequential_container(stream, c);
    return stream;
}

template<typename T, size_t N> ostream& operator << (ostream& stream, const array<T, N>& c) {
    print_sequential_container(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const deque<T>& c) {
    print_sequential_container(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const stack<T>& c) {
    vector<T> v;
    while (not c.empty()) {
        v.pb(c.top());
        c.pop();
    }
    for (int i = ((int)v.size()) - 1; i >= 0; i--) {
        c.push(v[i]);
    }
    print_sequential_container(stream, v);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const queue<T>& c) {
    vector<T> v;
    while (not c.empty()) {
        v.pb(c.front());
        c.pop();
    }
    for (T e: v) {
        c.push(e);
    }
    print_sequential_container(stream, v);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const priority_queue<T>& c) {
    vector<T> v;
    while (not c.empty()) {
        v.pb(c.top());
        c.pop();
    }
    for (T e: v) {
        c.push(e);
    }
    print_sequential_container(stream, v);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const set<T>& c) {
    print_set(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const unordered_set<T>& c) {
    print_set(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const multiset<T>& c) {
    print_set(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const unordered_multiset<T>& c) {
    print_set(stream, c);
    return stream;
}

template<typename T1, typename T2> ostream& operator << (ostream& stream, const map<T1, T2>& c) {
    print_map(stream, c);
    return stream;
}

template<typename T1, typename T2> ostream& operator << (ostream& stream, const unordered_map<T1, T2>& c) {
    print_map(stream, c);
    return stream;
}

template<typename T1, typename T2> ostream& operator << (ostream& stream, const multimap<T1, T2>& c) {
    print_map(stream, c);
    return stream;
}

template<typename T1, typename T2> ostream& operator << (ostream& stream, const unordered_multimap<T1, T2>& c) {
    print_map(stream, c);
    return stream;
}

template<typename T1, typename T2> ostream& operator << (ostream& stream, const pair<T1, T2>& p) {
    stream << "(" << p.fi << ", " << p.se << ")";
    return stream;
}

template<typename T>
size_t make_hash(const T& v) {
    return std::hash<T>()(v);
}

size_t hash_combine(const size_t& h, const size_t& v) {
    return h ^ (v + 0x9e3779b9 + (h << 6) + (h >> 2));
}

namespace std {
    template <typename T1, typename T2>
    struct hash<pair<T1, T2>> {
    public:
        size_t operator()(const pair<T1, T2>& p) const {
            return hash_combine(make_hash(p.fi), make_hash(p.se));
        }
    };
};

template<typename T>
struct hash_container
{
    size_t operator()(const T& c) const {
        size_t h = 0;
        for(const auto& e: c) {
            h = hash_combine(h, make_hash(e));
        }
        return h;
    }
};

typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpii;
typedef vector<vi> vvi;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef pair<ll, ll> pll;
typedef double ld;

template<typename T> bool amin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<typename T> bool amax(T &a, T b) { return a < b ? (a = b, true) : false; }

const int mod = 1000000007;
const int inf = 1000000000;
const ll infll = (ll)inf * (ll)inf;
const int maxn = 100100;

vector<vpii> g;
vector<char> used;
vll pos;

bool dfs(int i, ll p, ll& mmin, ll& mmax) {
    pos[i] = p;
    used[i] = 1;
    mmin = min(mmin, p);
    mmax = max(mmax, p);
    bool res = true;
    for (auto w: g[i]) {
        int j = w.fi, d = w.se;
        if (!used[j]) {
            res = dfs(j, p + d, mmin, mmax);
        } else {
            if (pos[j] - pos[i] != d) {
                DEBUG(pos[j]);
                DEBUG(pos[i]);
                DEBUG(j);
                DEBUG(i);
                DEBUG(d);
                res = false;
            }
        }
        if (not res) {
            break;
        }
    }
    return res;
}

class TaskB {
public:
    void solve(istream& in, ostream& out) {
        g.clear();
        used.clear();
        pos.clear();
        int n, m;
        in >> n >> m;
        g.resize(n);
        used.resize(n, 0);
        pos.resize(n);
        forn(i, m) {
            int l, r, d;
            in >> l >> r >> d;
            --l;
            --r;
            g[l].pb({r, d});
            g[r].pb({l, -d});
        }
        fill(all(pos), infll);
        forn(i, n) {
            if (!used[i]) {
                ll mmin = 2 * inf + 100, mmax = -2 * inf - 100;
                bool res = dfs(i, 0ll, mmin, mmax);
                if (not res) {
                    out << "No";
                    return;
                }
                if (mmax - mmin > inf) {
                    out << "No";
                    return;
                }
            }
        }
        out << "Yes";
    }
};


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    TaskB solver;
    std::istream& in(std::cin);
    std::ostream& out(std::cout);
    solver.solve(in, out);
    return 0;
}


Measured memory_bytes: 15616