// Original C++ solution (slower):
# include <iostream>

# include <algorithm>

# include <vector>

# include <string>

# include <set>

# include <map>

# include <cmath>

# include <iomanip>

# include <functional>

# include <utility>

# include <stack>

# include <queue>

# include <list>

# include <tuple>

# include <unordered_map>

# include <numeric>

# include <complex>

# include <bitset>

using namespace std;

using LL = long long;

using ULL = unsigned long long;

typedef pair<LL, LL> P;

constexpr int INF = 2000000000;

constexpr int HINF = INF / 2;

constexpr double DINF = 100000000000000000.0;

constexpr long long LINF = 9223372036854775807;

constexpr long long HLINF = 4500000000000000000;

constexpr long long MMOD = 500000004;

const double PI = acos(-1);

int dx[4] = { 0,1,0,-1 }, dy[4] = { 1,0,-1,0 };

# define ALL(x)      (x).begin(),(x).end()

# define UNIQ(c)     (c).erase(unique(ALL((c))), end((c)))

# define mp          make_pair

# define eb          emplace_back

# define FOR(i,a,b)  for(int i=(a);i<(b);i++)

# define RFOR(i,a,b) for(int i=(a);i>=(b);i--)

# define REP(i,n)    FOR(i,0,n)

# define INIT        std::ios::sync_with_stdio(false);std::cin.tie(0)



vector<pair<int,LL>> G[101010];



LL l[202020], r[202020], d[202020];

bool used[101010];

LL pos[101010];

int n, m;



bool serch(int p) {

	queue<int>q;

	q.push(p);



	while (!q.empty()) {

		int Pos = q.front();

		q.pop();

		used[Pos] = true;

		REP(i, G[Pos].size()) {

			if (!used[G[Pos][i].first]) {

				q.push(G[Pos][i].first);

				used[G[Pos][i].first] = true;

				pos[G[Pos][i].first] = pos[Pos] + G[Pos][i].second;

			}

			else {

				if (pos[Pos] + G[Pos][i].second != pos[G[Pos][i].first])return false;

			}

		}

	}

	return true;

}





int main() {

	cin >> n >> m;

	int first;

	REP(i, m) {

		cin >> l[i] >> r[i] >> d[i];

		l[i]--, r[i]--;

		if (!i)first = l[i];

		G[r[i]].emplace_back(mp(l[i], d[i]));

		G[l[i]].emplace_back(mp(r[i], -d[i]));

	}

	REP(i, n)pos[i] = LINF;

	REP(i, n) {

		if (!used[i]) {

			pos[i] = 0;

			if (serch(i) == false) {

				cout << "No" << endl;

				return 0;

			}



		}

	}

	cout << "Yes" << endl;

}

// Optimized solution to the same problem (faster):
# include <iostream>

# include <algorithm>

# include <vector>

# include <string>

# include <set>

# include <map>

# include <cmath>

# include <iomanip>

# include <functional>

# include <utility>

# include <stack>

# include <queue>

# include <list>

# include <tuple>

# include <unordered_map>

# include <numeric>

# include <complex>

# include <bitset>

using namespace std;

using LL = long long;

using ULL = unsigned long long;

typedef pair<LL, LL> P;

constexpr int INF = 2000000000;

constexpr int HINF = INF / 2;

constexpr double DINF = 100000000000000000.0;

constexpr long long LINF = 9223372036854775807;

constexpr long long HLINF = 4500000000000000000;

constexpr long long MMOD = 500000004;

const double PI = acos(-1);

int dx[4] = { 0,1,0,-1 }, dy[4] = { 1,0,-1,0 };

# define ALL(x)      (x).begin(),(x).end()

# define UNIQ(c)     (c).erase(unique(ALL((c))), end((c)))

# define mp          make_pair

# define eb          emplace_back

# define FOR(i,a,b)  for(int i=(a);i<(b);i++)

# define RFOR(i,a,b) for(int i=(a);i>=(b);i--)

# define REP(i,n)    FOR(i,0,n)

# define INIT        std::ios::sync_with_stdio(false);std::cin.tie(0)



template <typename T>

struct WeightedUnionFind {

	LL n;

	T d;

	vector<LL> r, p;

	vector<T> ws;

	WeightedUnionFind() {}

	WeightedUnionFind(LL sz, T d_) :

		n(sz), d(d_), r(n, 1), p(n), ws(n, d) {

		iota(p.begin(), p.end(), 0);

	}

	LL find(LL x) {

		if (x == p[x]) {

			return x;

		}

		else {

			LL t = find(p[x]);

			ws[x] += ws[p[x]];

			return p[x] = t;

		}

	}

	T weight(LL x) {

		find(x);

		return ws[x];

	}

	bool same(LL x, LL y) {

		return find(x) == find(y);

	}

	void unite(LL x, LL y, T w) {

		w += weight(x);

		w -= weight(y);

		x = find(x); y = find(y);

		if (x == y) return;

		if (r[x]<r[y]) swap(x, y), w = -w;

		r[x] += r[y];

		p[y] = x;

		ws[y] = w;

	}

	T diff(LL x, LL y) {

		return weight(y) - weight(x);

	}

};



int main() {

	LL n, m;

	cin >> n >> m;

	WeightedUnionFind<LL> wuf(n + 1, 0);

	for (LL i = 0; i<m; i++) {

		LL l, r, d;

		cin >> l >> r >> d;

		l--; r--;

		if (wuf.same(l, r)) {

			if (wuf.diff(l, r) != d) {

				cout << "No" << endl;

				return 0;

			}

		}

		else {

			wuf.unite(l, r, d);

		}

	}

	cout << "Yes" << endl;

}

// Fastest known solution for this problem: