// Slower C++ solution:
#include <iostream>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <algorithm>

#include <limits.h>

#include <vector>

#include <map>

#include <stack>

#include <queue>

#include <math.h>

#define ll long long

#define MSET(x) memset((x), 0, sizeof((x)))

#define MMSET(x) memset((x), -1, sizeof((x)))

#define rep(i, a, b) for ( ll (i) = a; (i) < (b) ; (i) ++ )

#define repA(i, a, b) for ( ll (i) = a ;  (i) <= (b) ; (i) ++ )

#define repD(i, a, b) for ( ll (i) = a; (i) >= (b) ; (i) -- )

#define fi first

#define se second

#define pb push_back

#define mfind(m, item) ((m).find((item)) != (m).end())

#define mp(a,b) make_pair((a),(b))

#define mt(a,b,c) make_pair(make_pair((a),(b)), (c))

#define tfi first.first

#define tse first.second

#define tth second

#define prll cout << endl

#define tri pair<pair<ll, ll>, ll>

using namespace std;



int n,m;

int cnt[100002], ans[100002];



void find(int x){

    if ( ans[x] == x ) return;

    find(ans[x]);

    cnt[x] += cnt[ans[x]], ans[x] = ans[ans[x]];

}



bool has = false;



int main(){

    while ( cin >> n >> m ) {

        MSET(cnt); MSET(ans); has = false;

        for ( int i = 1 ; i <= n ; ++ i ) ans[i] = i;

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

            int l, r, d;

            scanf("%d %d %d", &l, &r, &d);

            find(l); find(r);

            if ( ans[l] == ans[r] ){

                if ( cnt[l] + d != cnt[r] ) {

                    has = true;

                }

            }

            else {

                cnt[ans[r]] = cnt[l] + d - cnt[r];

                ans[ans[r]] = ans[l];

            }

        }

        cout << (has ? "No" : "Yes" ) << endl;

    }

}


// Faster C++ solution for the same problem (measured speedup: 1.7822810486115979x):
#include <iostream>

#include <vector>

#include <algorithm>

#include <map>

#include <set>

#include <unordered_map>

#include <unordered_set>

#include <tuple>

#include <iomanip>

//#include <cmath>

#include <queue>

#include <deque>

#include <stack>

//#pragma GCC optimize("Ofast")

//#pragma GCC target("avx,avx2")

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

#define rall(x) (x).rbegin(), (x).rend()

typedef long double ld;

typedef long long ll;

typedef double db;

#define endl '\n'

#define pb push_back

#define pii pair<ll, ll>

#define ff first

#define ss second

#define sz(x) (ll)(x).size()

#define optimize1() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)

#pragma warning(disable:4996)



using namespace std;



const ll MX = 2e5 + 10, INF = 1e9 + 1;

ll n, m, t, d[MX], l[MX], r[MX], a[MX];

bool used[MX];

vector<vector<int>> g;



bool dfs(int v) {

	used[v] = true;

	bool f = true;

	for (auto c : g[v]) {

		int tmp = a[v], pos = l[c] + r[c] - v;

		if (l[c] == v)

			tmp += d[c];

		else

			tmp -= d[c];

		if (used[pos])

			f = f && (a[pos] == tmp);

		else {

			a[pos] = tmp;

			f = f && dfs(pos);

		}

	}

	return f;

}



signed main() {

	optimize1();

	cin >> n >> m;

	g.resize(n + 1);

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

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

		g[l[i]].pb(i);

		g[r[i]].pb(i);

	}

	for (int i = 1; i <= n; ++i) {

		if (used[i])

			continue;

		a[i] = 0;

		if (!dfs(i)) {

			cout << "No" << endl;

			return 0;

		}

	}

	cout << "Yes" << endl;

	return 0;

}