// Slower C++ solution:
/*

Problem:People on a Line

Algorithm:"linear" DFS

Status:

*/



#include <iostream>

#include <cstdio>

#include <cmath>

#include <algorithm>

#include <string>

#include <vector>

#include <map>

#include <queue>

#include <deque>

#include <set>

#include <sstream>

#include <utility>

#include <list>

#include <ctime>

#include <memory.h>

#include <stack>

#include <stdio.h>

#include <string.h>



using namespace std;



const int INF=1e9+7;



vector<pair<int,int> > nei[100005];

int pos[100005];

int n,m;

bool used[100005];

bool exist[100005];



void dfs(int x,int cur){

	pos[x]=cur;

	used[x]=true;

	for(int i=0;i<nei[x].size();i++){

		if(used[nei[x][i].first]){

			if(pos[nei[x][i].first]-cur!=nei[x][i].second){

				cout<<"No"<<endl;

				exit(0);

			}

		}

		else{

			dfs(nei[x][i].first,cur+nei[x][i].second);

		}

	}

}



int main()

{

	scanf("%d%d",&n,&m);

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

		int l,r,d;

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

		l--;r--;

		exist[l]=true;exist[r]=true;

		nei[l].push_back(make_pair(r,d));

		nei[r].push_back(make_pair(l,-d));

	}

	

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

		if(!exist[i])continue;

		if(!used[i]){

			dfs(i,0);

		}

	}

	cout<<"Yes"<<endl;

	

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.4396114742964454x):
#include <bits/stdc++.h>

#include <unordered_map>

#include <unordered_set>

using namespace std;

#define int long long

#define eb emplace_back

#define ef emplace_front

#define rep(i, x, n) for (int i = x; i < n; ++i)

#define mp make_pair

#define fi first

#define se second

#define ii pair<int, int>

#define endl '\n'

#define vi vector<int>

#define vii vector<pair<int, int>>

#define reverse(s) reverse(s.begin(), s.end())

#define ld long double

#define vs vector<string>

#define inf INT_MAX

#define vc vector<char>

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

#define vb vector<bool>

#define lb(a, x) lower_bound(a.begin(), a.end(), x)

#define ub(a, x) upper_bound(a.begin(), a.end(), x) 

#define vvi vector<vi>

#define mine(a) min_element(a.begin(),a.end())

#define maxe(a) max_element(a.begin(), a.end())

#define iota(a,i) iota(a.begin(),a.end(),i)

#define fileopen(filename) if (fopen(filename".INP", "r")) {freopen(filename".INP", "r", stdin);freopen(filename".OUT", "w", stdout);}

int n, m;

map<ii, int> a;

vi par, val;

vvi adj;

vb d;

int findset(int x) {

	int u = x;

	while (par[x] != -1) {

		x = par[x];

		par[u] = x;

	}

	return x;

}

bool sameset(int x, int y) {

	return findset(x) == findset(y);

}

void unionset(int x, int y) {

	x = findset(x);

	y = findset(y);

	if (x == y) return;

	par[x] = y;

}

void dfs(int x) {

	for (int i : adj[x]) {

		if (d[i] == 0) {

			d[i] = 1;

			val[i] = val[x] + a[mp(x, i)];

			dfs(i);

		}

		else if (val[i] != val[x] + a[mp(x, i)]) {

			cout << "No";

			exit(0);

		}

	}

}

signed main() {

	fastio;

	cin >> n >> m;

	par.resize(n + 1, -1);

	adj.resize(n + 1);

	d.resize(n + 1, 0);

	val.resize(n + 1, 0);

	while (m--) {

		int x, y, z;

		cin >> x >> y >> z;

		a[mp(x, y)] = z;

		a[mp(y, x)] = -z;

		unionset(x, y);

		adj[x].emplace_back(y);

		adj[y].emplace_back(x);

	}

	rep(i, 1, n + 1) {

		if (d[i] == 0) {

			int x = findset(i);

			d[x] = 1;

			val[x] = 0;

			dfs(x);

		}

	}

	cout << "Yes";

	return 0;

}