using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Numerics;
using System.IO;
using System.Text.RegularExpressions;
using System.Text;
using System.Diagnostics;
using System.Globalization;
using static System.Math;

namespace A
{
	class Program
	{
		// variables
		int N;
		int M;

		void Run(string[] args)
		{
			// main program
			N = Int;
			M = Int;
			var unionFind = new UnionFind<int, IntOp>(N);
			if (List(M, () => {
				var l = Int - 1;
				var r = Int - 1;
				var d = Int;
				return unionFind.Unite(l, r, d) || unionFind.Diff(l, r) == d;
			}).All(b => b))
			{
				PrintLine("Yes");
			}
			else
			{
				PrintLine("No");
			}
		}

		// methods


		// utilities
		static void Main(string[] args)
		{
			new Program().Run(args);
#if DEBUG
			Console.Write("Press any key...");
			Console.ReadKey();
#endif
		}

		/// <summary>
		/// Make an array
		/// </summary>
		/// <typeparam name="T">type of element</typeparam>
		/// <param name="count">number of elements</param>
		/// <param name="input">element generator</param>
		/// <returns>array</returns>
		static T[] List<T>(int count, Func<int, T> input)
		{
			var list = new T[count];
			for (var i = 0; i < count; ++i)
			{
				list[i] = input(i);
			}
			return list;
		}
		/// <summary>
		/// Make an array
		/// </summary>
		/// <typeparam name="T">type of element</typeparam>
		/// <param name="count">number of elements</param>
		/// <param name="input">element generator</param>
		/// <returns>array</returns>
		static T[] List<T>(int count, Func<T> input) => List(count, i => input());

		/// <summary>
		/// Output any value.
		/// </summary>
		/// <typeparam name="T">type of value.</typeparam>
		/// <param name="value">value</param>
		[DebuggerNonUserCode]
		static void Print<T>(T value)
		{
			Console.Write(value);
		}
		/// <summary>
		/// Output any value on a line.
		/// </summary>
		/// <typeparam name="T">type of value</typeparam>
		/// <param name="value">value</param>
		[DebuggerNonUserCode]
		static void PrintLine<T>(T value)
		{
			Console.WriteLine(value);
		}

		/// <summary>
		/// Input a word
		/// </summary>
		static string Word
		{
			[DebuggerNonUserCode]
			get
			{
				char c;
				while (char.IsWhiteSpace(c = (char)Console.Read()))
				{
					continue;
				}

				var builder = new StringBuilder();
				do
				{
					builder.Append(c);
				}
				while (!char.IsWhiteSpace(c = (char)Console.Read()));

				return builder.ToString();
			}
		}
		/// <summary>
		/// Input a line
		/// </summary>
		static string Line
		{
			[DebuggerNonUserCode]
			get
			{
				return Console.ReadLine();
			}
		}
		/// <summary>
		/// Input bool
		/// </summary>
		static bool Bool
		{
			[DebuggerNonUserCode]
			get
			{
				return bool.Parse(Word);
			}
		}
		/// <summary>
		/// Input char
		/// </summary>
		static char Char
		{
			[DebuggerNonUserCode]
			get
			{
				return char.Parse(Word);
			}
		}
		/// <summary>
		/// Input byte
		/// </summary>
		static byte Byte
		{
			[DebuggerNonUserCode]
			get
			{
				return byte.Parse(Word);
			}
		}
		/// <summary>
		/// Input ushort
		/// </summary>
		static ushort UShort
		{
			[DebuggerNonUserCode]
			get
			{
				return ushort.Parse(Word);
			}
		}
		/// <summary>
		/// Input uint
		/// </summary>
		static uint UInt
		{
			[DebuggerNonUserCode]
			get
			{
				return uint.Parse(Word);
			}
		}
		/// <summary>
		/// Input ulong
		/// </summary>
		static ulong ULong
		{
			[DebuggerNonUserCode]
			get
			{
				return ulong.Parse(Word);
			}
		}
		/// <summary>
		/// Input sbyte
		/// </summary>
		static sbyte SByte
		{
			[DebuggerNonUserCode]
			get
			{
				return sbyte.Parse(Word);
			}
		}
		/// <summary>
		/// Input short
		/// </summary>
		static short Short
		{
			[DebuggerNonUserCode]
			get
			{
				return short.Parse(Word);
			}
		}
		/// <summary>
		/// Input int
		/// </summary>
		static int Int
		{
			[DebuggerNonUserCode]
			get
			{
				return int.Parse(Word);
			}
		}
		/// <summary>
		/// Input long
		/// </summary>
		static long Long
		{
			[DebuggerNonUserCode]
			get
			{
				return long.Parse(Word);
			}
		}
		/// <summary>
		/// Input decimal
		/// </summary>
		static decimal Decimal
		{
			[DebuggerNonUserCode]
			get
			{
				return decimal.Parse(Word);
			}
		}
		/// <summary>
		/// Input variable length integer
		/// </summary>
		static BigInteger Integer
		{
			[DebuggerNonUserCode]
			get
			{
				return BigInteger.Parse(Word);
			}
		}
		/// <summary>
		/// Input float
		/// </summary>
		static float Float
		{
			[DebuggerNonUserCode]
			get
			{
				return float.Parse(Word);
			}
		}
		/// <summary>
		/// Input double
		/// </summary>
		static double Double
		{
			[DebuggerNonUserCode]
			get
			{
				return double.Parse(Word);
			}
		}

		/// <summary>
		/// Input hex int
		/// </summary>
		static int Hex
		{
			[DebuggerNonUserCode]
			get
			{
				return int.Parse(Word, NumberStyles.HexNumber);
			}
		}
		/// <summary>
		/// Input hex int
		/// </summary>
		static int HexInt
		{
			[DebuggerNonUserCode]
			get
			{
				return Hex;
			}
		}
		/// <summary>
		/// Input hex long
		/// </summary>
		static long HexLong
		{
			[DebuggerNonUserCode]
			get
			{
				return long.Parse(Word, NumberStyles.HexNumber);
			}
		}
		/// <summary>
		/// Input variable length hex integer
		/// </summary>
		static BigInteger HexInteger
		{
			[DebuggerNonUserCode]
			get
			{
				return BigInteger.Parse(Word, NumberStyles.HexNumber);
			}
		}

		/// <summary>
		/// Union-find tree
		/// </summary>
		class UnionFind : UnionFind<Unit, UnitOp>
		{
			/// <param name="count">number of elements</param>
			public UnionFind(int count) : base(count)
			{}
		}

		/// <summary>
		/// Union-find tree
		/// </summary>
		class UnionFind<TPotential, TPotentialOp>
			where TPotentialOp : struct, IAddable<TPotential>
		{
			/// <summary>
			/// parent indices
			/// </summary>
			readonly int[] Parent;

			/// <summary>
			/// tree rank
			/// </summary>
			readonly int[] Rank;

			/// <summary>
			/// potential
			/// </summary>
			readonly TPotential[] DiffPotential;

			/// <param name="count">number of elements</param>
			public UnionFind(int count)
			{
				Parent = List(count, i => i);
				Rank = List(count, () => 0);
				DiffPotential = List(count, () => default(TPotentialOp).Zero);
			}

			/// <summary>
			/// Get root element
			/// </summary>
			/// <param name="x">element index</param>
			/// <returns>root element index of <c>x</c></returns>
			public int Root(int x)
			{
				if (Parent[x] == x)
				{
					return x;
				}
				else
				{
					var root = Root(Parent[x]);
					DiffPotential[x] = default(TPotentialOp).Add(DiffPotential[x], DiffPotential[Parent[x]]);
					return Parent[x] = root;
				}
			}

			/// <summary>
			/// Get whether two elements belong to the same set.
			/// </summary>
			/// <param name="x">first element index</param>
			/// <param name="y">second element index</param>
			/// <returns>whether two elements belong to the same set</returns>
			public bool Same(int x, int y)
				=> Root(x) == Root(y);


			/// <summary>
			/// Unite two elements
			/// </summary>
			/// <param name="x">first element index</param>
			/// <param name="y">second element index</param>
			public bool Unite(int x, int y)
				=> Unite(x, y, default(TPotentialOp).Zero);

			/// <summary>
			/// Unite two elements
			/// </summary>
			/// <param name="x">first element index</param>
			/// <param name="y">second element index</param>
			/// <param name="potential">potential from <c>x</c> to <c>y</c></param>
			public bool Unite(int x, int y, TPotential potential)
			{
				potential = default(TPotentialOp).Add(potential, Potential(x));
				potential = default(TPotentialOp).Subtract(potential, Potential(y));
				x = Root(x);
				y = Root(y);

				if (x == y) return false;

				if (Rank[x] < Rank[y])
				{
					// Join x to y
					Parent[x] = y;
					DiffPotential[x] = default(TPotentialOp).Negate(potential);
				}
				else
				{
					// Join y to x
					Parent[y] = x;
					if (Rank[x] == Rank[y]) ++Rank[x];
					DiffPotential[y] = potential;
				}
				return true;
			}

			/// <summary>
			/// Get potential difference from root.
			/// </summary>
			/// <param name="x">element index</param>
			/// <returns>potential difference between the element and the root</returns>
			public TPotential Potential(int x)
			{
				Root(x);
				return DiffPotential[x];
			}

			/// <summary>
			/// Get potential difference between two element.
			/// </summary>
			/// <param name="x">first element index</param>
			/// <param name="y">second element index</param>
			/// <returns>potential difference between two element</returns>
			public TPotential Diff(int x, int y)
				=> default(TPotentialOp).Subtract(Potential(y), Potential(x));
		}

		struct Unit
		{ }
		struct UnitOp : IDividable<Unit>
		{
			public Unit Divide(Unit x, Unit y) => default(Unit);
			public Unit One => default(Unit);
			public Unit Multiply(Unit x, Unit y) => default(Unit);
			public Unit Zero => default(Unit);
			public Unit Negate(Unit x) => default(Unit);
			public Unit Add(Unit x, Unit y) => default(Unit);
		}
		struct IntOp : IDividable<int>
		{
			public int Zero => 0;
			public int One => 1;
			public int Negate(int x) => -x;
			public int Add(int x, int y) => x + y;
			public int Multiply(int x, int y) => x * y;
			public int Divide(int x, int y) => x / y;
		}
		struct LongOp : IDividable<long>
		{
			public long Zero => 0L;
			public long One => 1L;
			public long Negate(long x) => -x;
			public long Add(long x, long y) => x + y;
			public long Multiply(long x, long y) => x * y;
			public long Divide(long x, long y) => x / y;
		}
		struct FloatOp : IDividable<float>
		{
			public float Zero => 0.0F;
			public float One => 1.0F;
			public float Negate(float x) => -x;
			public float Add(float x, float y) => x + y;
			public float Multiply(float x, float y) => x * y;
			public float Divide(float x, float y) => x / y;
		}
		struct DoubleOp : IDividable<double>
		{
			public double Zero => 0.0;
			public double One => 1.0;
			public double Negate(double x) => -x;
			public double Add(double x, double y) => x + y;
			public double Multiply(double x, double y) => x * y;
			public double Divide(double x, double y) => x / y;
		}
	}

	interface IDividable<T> : IMultipliable<T>
	{
		T Divide(T x, T y);
	}
	interface IMultipliable<T> : IAddable<T>
	{
		T One { get; }
		T Multiply(T x, T y);
	}
	interface IAddable<T>
	{
		T Zero { get; }
		T Negate(T x);
		T Add(T x, T y);
	}

	static class OpetationExtensions
	{
		public static T Subtract<T, TOp>(this TOp op, T x, T y)
			where TOp : struct, IAddable<T>
		{
			return default(TOp).Add(x, default(TOp).Negate(y));
		}
		public static T Sum<T, TOp>(this TOp op, params T[] items)
			where TOp : struct, IAddable<T>
		{
			var sum = default(TOp).Zero;
			foreach (var item in items)
				sum = default(TOp).Add(sum, item);
			return sum;
		}
		public static T Product<T, TOp>(this TOp op, params T[] items)
			where TOp : struct, IMultipliable<T>
		{
			var sum = default(TOp).One;
			foreach (var item in items)
				sum = default(TOp).Multiply(sum, item);
			return sum;
		}
	}
}


Measured memory_bytes: 16528