# Original solution
import heapq

INF = float('inf')


class UnionFind:
    def __init__(self, size: int):
        self.__size = size
        self.__root = [-1] * size

    def find(self, u: int)->int:
        if self.__root[u] < 0:
            return u
        self.__root[u] = self.find(self.__root[u])
        return self.__root[u]

    def same(self, u: int, v: int)->bool:
        return self.find(u) == self.find(v)

    def unite(self, u: int, v: int):
        x, y = self.find(u), self.find(v)

        if x == y:
            return

        if self.__root[y] < self.__root[x]:
            x, y = y, x

        self.__root[x] += self.__root[y]
        self.__root[y] = x

    def print(self):
        print(self.__root)


class PriorityQueue:
    def __init__(self):
        self.__queue = []
        self.__count = 0

    def enqueue(self, v):
        self.__count += 1
        heapq.heappush(self.__queue, v)

    def dequeue(self):
        self.__count -= 1
        return heapq.heappop(self.__queue)

    def is_empty(self)->bool:
        return self.__count == 0


def dijkstra(V: int, E: list, s: int, t: int)->int:
    '''dijkstra 法を使って u -> v の距離を求める。
    :param V: 頂点数
    :param E: 辺の集合
    :param s: 始点
    :param t: 終点
    :return: 距離
    '''
    d = [INF] * (V)
    d[s] = 0

    q = PriorityQueue()
    for v in range(V):
        q.enqueue((d[v], v))

    while not q.is_empty():
        _, u = q.dequeue()
        for v, c in E[u]:
            if d[u] + c < d[v]:
                d[v] = d[u] + c
                q.enqueue((d[v], v))

    return d[t]


def people_on_a_line(N: int, M: int, queries: list)->bool:
    E = [[] for _ in range(N)]
    uf = UnionFind(N)
    for l, r, d in queries:
        if uf.same(l-1, r-1):
            if d != dijkstra(N, E, l-1, r-1):
                return False
        else:
            uf.unite(l-1, r-1)
            E[l-1].append((r-1, d))
            E[r-1].append((l-1, -d))

    return True


if __name__ == "__main__":
    M = 0
    N, M = map(int, input().split())
    queries = [tuple(int(s) for s in input().split()) for _ in range(M)]
    yes = people_on_a_line(N, M, queries)
    print('Yes' if yes else 'No')


# Optimized solution
class WeightenedUnionFind:
    def __init__(self, size: int):
        self.__size = size
        self.__root = [-1] * size
        self.__diff_weight = [0] * size

    def find(self, u: int)->int:
        if self.__root[u] < 0:
            return u
        r = self.find(self.__root[u])
        self.__diff_weight[u] += self.__diff_weight[self.__root[u]]
        self.__root[u] = r
        return self.__root[u]

    def same(self, u: int, v: int)->bool:
        return self.find(u) == self.find(v)

    def unite(self, u: int, v: int, w: int):
        w += self.weight(u)
        w -= self.weight(v)

        x, y = self.find(u), self.find(v)

        if x == y:
            return

        if self.__root[y] < self.__root[x]:
            x, y = y, x
            w = -w

        self.__root[x] += self.__root[y]
        self.__root[y] = x

        self.__diff_weight[y] = w

    def weight(self, u: int)->int:
        self.find(u)
        return self.__diff_weight[u]

    def diff_weight(self, u: int, v: int)->int:
        return self.weight(v) - self.weight(u)


def people_on_a_line(N: int, M: int, queries: list)->bool:
    uf = WeightenedUnionFind(N)
    for l, r, d in queries:
        if uf.same(l-1, r-1):
            if d != uf.diff_weight(l-1, r-1):
                return False
        else:
            uf.unite(l-1, r-1, d)

    return True


if __name__ == "__main__":
    M = 0
    N, M = list(map(int, input().split()))
    queries = [tuple(int(s) for s in input().split()) for _ in range(M)]
    yes = people_on_a_line(N, M, queries)
    print(('Yes' if yes else 'No'))