#include <cstdio>
#include <vector>
#include <utility>
using namespace std;
typedef pair<int, int> T;

/*
	사실 이 문제에서 사람의 절대적인 위치는 중요하지 않다.
	대신 사람과 사람 사이의 거리 관계가 올바른지를 판단해야 한다.

	각 사람들을 정점으로 두고, 사람 사이의 거리를 간선으로 두자.
	Li -> Ri로 갈 때 그래프에 Ri -> Li (가중치는 Di)인 간선을 추가한다.
	
	이 문제에서 판단해야 하는 것은 크게 2가지로 나뉜다.
	- 이 그래프에 순환이 있는가?
	- 이 그래프에서 각 정점의 rank를 root로부터 정점까지 경로의 가중치 합
	  으로 정의할 때, 목적지가 같은 정점에 대해 서로 다른 경로를 탐색할 
	  경우 rank가 일치하는가?
	
	첫 번째 조건은 직관적으로 와닿는다. 상식적으로 사람 1, 2가 왼쪽 오른쪽에
	서 있으면서 사람 2, 1이 왼쪽 오른쪽에 서있을 수는 없기 때문이다.

	두 번째 조건이 조금 어렵다.
	a->b 간의 거리가 3이라면, 모든 k에 대하여 a->k->b의 거리도 3이어야 한다.
	이걸 빠르게 계산하는 방법은 root로부터 전위 탐색을 수행하면서 그 거리를
	메모하는 것이다. 그러면, 두 번째 방문 시 구한 거리가 일치하는지 여부로
	체크를 할 수 있다.

	두 부분 문제 모두 dfs를 사용하므로 O(V + E)의 시간 복잡도로 문제를 풀 수 있다.
*/

int N, M, l, r, d;
int dist[100001];
int stime[100001];
int etime[100001];
vector <vector <T> > G;

int timestamp = 0;
bool dfs(int v, int ranksum = -1)
{
	stime[v] = timestamp++;
	if (ranksum >= 0)
		dist[v] = ranksum;
	else if (v != 0 && G[v].size() >= 2)
		ranksum = 0;
	for (int e = 0; e < G[v].size(); ++e)
	{
		int nb = G[v][e].first;
		if (stime[nb] != -1 && etime[nb] == -1)
		{
			//printf("CYCLE DETECTED at: %d from %d\n", G[v][e].first, v);
			return true;
		}
		if (ranksum >= 0 && dist[nb] >= 0 &&
			dist[nb] != G[v][e].second + ranksum)
		{
			//printf("RANK FAIL at %d from %d, rank is %d which should be %d\n", G[v][e].first, v, dist[G[v][e].first], G[v][e].second + ranksum);
			return true;
		}
		if (etime[nb] == -1 && dfs(nb, ranksum >= 0 ? G[v][e].second + ranksum : -1))
			return true;
	}
	etime[v] = timestamp;
	return false;
}

int main(void)
{
	//freopen("input.txt", "r", stdin);
	scanf("%d %d", &N, &M);
	for (int n = 0; n <= N; ++n)
	{
		G.push_back(vector <T>());
		dist[n] = -1;
		stime[n] = -1;
		etime[n] = -1;
		if (n > 0)
			G[0].push_back(T(n, 0));
	}
	for (int m = 0; m < M; ++m)
	{
		scanf("%d %d %d", &l, &r, &d);
		G[l].push_back(T(r, d));
	}
	
	if (dfs(0))
		printf("No");
	else
		printf("Yes");
	return 0;
}