CodeEff/ECCO huggingface dataset:
# Original solution
import sys
input = sys.stdin.readline

N, M = list(map(int, input().split()))

graph = [[] for _ in range(N + 1)]
for _ in range(M):
    L, R, D = list(map(int, input().split()))
    graph[L].append((R, D))
    graph[R].append((L, -D))

d = ['a'] * (N + 1)

def calc(start): #startからの連結成分をチェックする
    d[start] = 0
    stack = [start]
    while len(stack) != 0:
        tmp = stack.pop()
        for next_, diff in graph[tmp]:
            if d[next_] == 'a':
                d[next_] = d[tmp] + diff
                stack.append(next_)
            else:
                if d[next_] == d[tmp] + diff:
                    pass
                else:
                    print ('No')
                    exit()
    return 

# for i in graph:
#     print (i)

for i in range(1, N):
    if d[i] == 'a':
        calc(i)
print ('Yes')


# Optimized solution
import sys
input = sys.stdin.readline

N, M = list(map(int, input().split()))

graph = [[] for _ in range(N + 1)]
for _ in range(M):
    L, R, D = list(map(int, input().split()))
    graph[L].append((R, D))
    graph[R].append((L, -D))

d = [None] * (N + 1)

def calc(start): #startからの連結成分をチェックする
    d[start] = 0
    stack = [start]
    while len(stack) != 0:
        tmp = stack.pop()
        for next_, diff in graph[tmp]:
            if d[next_] == None:
                d[next_] = d[tmp] + diff
                stack.append(next_)
            else:
                if d[next_] == d[tmp] + diff:
                    pass
                else:
                    print ('No')
                    exit()
    return 

# for i in graph:
#     print (i)

for i in range(1, N):
    if d[i] == None:
        calc(i)
print ('Yes')
# Original solution
from collections import deque
import sys
input = sys.stdin.readline

N, M = list(map(int, input().split()))

G = [[] for _ in range(N + 1)]

for _ in range(M):
    l, r, d = list(map(int, input().split()))
    G[l].append((r, -d))
    G[r].append((l, d))


MIN = -10 ** 18

lst = [MIN] * (N + 1)

que = deque()

for i in range(1, N + 1):
    if lst[i] == MIN:
        que.append(i)
        lst[i] = 0

    while que:
        tmp = que.popleft()
        for next_, d in G[tmp]:
            if lst[next_] == MIN:
                lst[next_] = lst[tmp] + d
                que.append(next_)
                continue
            
            if lst[next_] == lst[tmp] + d:
                continue
            else:
                print ('No')
                exit()

print ('Yes')


# Optimized solution
from collections import deque
import sys
input = sys.stdin.readline

N, M = list(map(int, input().split()))

G = [[] for _ in range(N + 1)]

for _ in range(M):
    l, r, d = list(map(int, input().split()))
    G[l].append((r, -d))
    G[r].append((l, d))


MIN = -10 ** 18

lst = [MIN] * (N + 1)

que = deque()
que_append = que.append
que_popleft = que.popleft

for i in range(1, N + 1):
    if lst[i] == MIN:
        que_append(i)
        lst[i] = 0

    while que:
        tmp = que_popleft()
        for next_, d in G[tmp]:
            if lst[next_] == MIN:
                lst[next_] = lst[tmp] + d
                que_append(next_)
                continue
            
            if lst[next_] == lst[tmp] + d:
                continue
            else:
                print ('No')
                exit()

print ('Yes')
# Original solution
from collections import deque
import sys
input = sys.stdin.readline

N, M = list(map(int, input().split()))

G = [[] for _ in range(N + 1)]

for _ in range(M):
    l, r, d = list(map(int, input().split()))
    G[l].append((r, -d))
    G[r].append((l, d))


MIN = -10 ** 18

lst = [MIN] * (N + 1)

que = deque()
que_append = que.append
que_popleft = que.popleft

for i in range(1, N + 1):
    if lst[i] == MIN:
        que_append(i)
        lst[i] = 0

    while que:
        tmp = que_popleft()
        for next_, d in G[tmp]:
            if lst[next_] == MIN:
                lst[next_] = lst[tmp] + d
                que_append(next_)
                continue
            
            if lst[next_] == lst[tmp] + d:
                continue
            else:
                print ('No')
                exit()

print ('Yes')


# Optimized solution
def main():
    from collections import deque
    import sys
    input = sys.stdin.readline

    N, M = list(map(int, input().split()))

    G = [[] for _ in range(N + 1)]

    for _ in range(M):
        l, r, d = list(map(int, input().split()))
        G[l].append((r, -d))
        G[r].append((l, d))


    MIN = -10 ** 18

    lst = [MIN] * (N + 1)

    que = deque()
    que_append = que.append
    que_popleft = que.popleft

    for i in range(1, N + 1):
        if lst[i] == MIN:
            que_append(i)
            lst[i] = 0

        while que:
            tmp = que_popleft()
            for next_, d in G[tmp]:
                if lst[next_] == MIN:
                    lst[next_] = lst[tmp] + d
                    que_append(next_)
                    continue
                
                if lst[next_] == lst[tmp] + d:
                    continue
                else:
                    print ('No')
                    exit()

    print ('Yes')

if __name__ == '__main__':
    main()
# Original solution
from collections import deque
n, m = list(map(int, input().split()))
graph = [[] for i in range(n)]
for i in range(m):
    l, r, d = list(map(int, input().split()))
    graph[l-1].append((r-1, d))
    graph[r-1].append((l-1, -d))

for i in range(n):
    x = [-1 for i in range(n)]
    if x[i] == -1:
        x[i] = 0
        q = deque([i])
        while q:
            s = q.popleft()
            for node, dist in graph[s]:
                if x[node] == -1:
                    q.append(node)
                    x[node] = x[s] + dist
                elif x[node] != x[s] + dist:
                    print("No")
                    exit()
print("Yes")

# Optimized solution
n, m = list(map(int, input().split()))

par = [i for i in range(n)]
rank = [0 for i in range(n)]
diff_weight = [0 for i in range(n)]


def root(x):
    if par[x] == x:
        return x
    r = root(par[x])
    diff_weight[x] += diff_weight[par[x]]
    par[x] = r
    return par[x]

def issame(x, y):
    return root(x) == root(y)

def weight(x):
    root(x)
    return diff_weight[x]

def diff(x, y):
    return weight(y) - weight(x)

def merge(x, y, w):
    w += weight(x)
    w -= weight(y)
    x = root(x)
    y = root(y)
    if x == y:
        return False
    if rank[x] < rank[y]:
        x, y = y, x
        w = -w
    if rank[x] == rank[y]:
        rank[x] += 1
    par[y] = x
    diff_weight[y] = w
    return True

for i in range(m):
    l, r, d = list(map(int, input().split()))
    if issame(l-1, r-1):
        di = diff(l-1, r-1)
        if di != d:
            print("No")
            exit()
    else:
        merge(l-1, r-1, d)

print("Yes")
# Original solution
from bisect import bisect_left
from copy import deepcopy
from operator import itemgetter

n, m = (int(x) for x in input().split())
LRD = [tuple(int(x) for x in input().split()) for _ in range(m)]
LRD.sort(key=itemgetter(0, 1))
INF = 10**18

while LRD:
    X = [INF] * n
    TBD = []  # To be determined
    X[LRD[0][0] - 1] = 0
    for l, r, d in LRD:
        l -= 1
        r -= 1
        if X[l] == X[r] == INF:
            TBD.append((l, r, d))
        elif X[l] != INF and X[r] == INF:
            X[r] = X[l] + d
        elif X[l] == INF and X[r] != INF:
            X[l] = X[r] - d
        else:
            if X[r] - X[l] != d:
                print("No")
                exit()
            else:
                continue
    LRD = deepcopy(TBD)
    LRD.sort(key=itemgetter(0, 1))
    X.sort()
    xmax = X[bisect_left(X, INF) - 1]
    xmin = X[0]
    if xmax - xmin >= 10**9:
        print("No")
        exit()

print("Yes")


# Optimized solution
n, m = (int(x) for x in input().split())
LRD = [tuple(int(x) for x in input().split()) for _ in range(m)]

G = [[] for _ in range(n)]
dist = dict()
for l, r, d in LRD:
    l -= 1
    r -= 1
    G[l].append(r)
    G[r].append(l)
    dist[(l, r)] = d
    dist[(r, l)] = -d

INF = 10**18
X = [INF] * n
for i in range(n):
    stack = [i]
    while stack:
        u = stack.pop()
        if X[u] == INF:
            X[u] = 0
        for v in G[u]:  # u -> v
            if X[v] == INF:
                X[v] = X[u] + dist[(u, v)]
                stack.append(v)
            else:
                if X[v] != X[u] + dist[(u, v)]:
                    print("No")
                    exit()

print("Yes")
# Original solution
#重み付きUnion-Find

#xの根を求める
def find(x):
    if par[x] < 0:
        return x
    else:
        px = find(par[x])
        wei[x] += wei[par[x]]
        par[x] = px
        return px

#xの根から距離
def weight(x):
    find(x)
    return wei[x]


#w[y]=w[x]+wとなるようにxとyを併合
def unite(x,y,w):
    w += wei[x]-wei[y]
    x = find(x)
    y = find(y)
    
    if x == y:
        return False
    else:
        #sizeの大きいほうがx
        if par[x] > par[y]:
            x,y = y,x
            w = -w
        par[x] += par[y]
        par[y] = x
        wei[y] = w
        return True

#xとyが同じ集合に属するかの判定
def same(x,y):
    return find(x) == find(y)

#xが属する集合の個数
def size(x):
    return -par[find(x)]

#x,yが同じ集合に属するときのwei[y]-wei[x]
def diff(x,y):
    return weight(y)-weight(x)

n,m = list(map(int,input().split()))

#初期化
#par:根なら-size,子なら親の頂点
#wei:親からの距離,根なら0
par = [-1]*n
wei = [0]*n

for i in range(m):
    l,r,d = list(map(int,input().split()))
    l,r = l-1,r-1
    if same(l,r):
        if d != diff(l,r):
            print('No')
            exit()
    else:
        unite(l,r,d)
print('Yes')
        


# Optimized solution
def main():
    import sys
    input = sys.stdin.readline
    #重み付きUnion-Find

    #xの根を求める
    def find(x):
        if par[x] < 0:
            return x
        else:
            px = find(par[x])
            wei[x] += wei[par[x]]
            par[x] = px
            return px

    #xの根から距離
    def weight(x):
        find(x)
        return wei[x]


    #w[y]=w[x]+wとなるようにxとyを併合
    def unite(x,y,w):
        w += wei[x]-wei[y]
        x = find(x)
        y = find(y)
        
        if x == y:
            return False
        else:
            #sizeの大きいほうがx
            if par[x] > par[y]:
                x,y = y,x
                w = -w
            par[x] += par[y]
            par[y] = x
            wei[y] = w
            return True

    #xとyが同じ集合に属するかの判定
    def same(x,y):
        return find(x) == find(y)

    #xが属する集合の個数
    def size(x):
        return -par[find(x)]

    #x,yが同じ集合に属するときのwei[y]-wei[x]
    def diff(x,y):
        return weight(y)-weight(x)

    n,m = list(map(int,input().split()))

    #初期化
    #par:根なら-size,子なら親の頂点
    #wei:親からの距離,根なら0
    par = [-1]*n
    wei = [0]*n

    for i in range(m):
        l,r,d = list(map(int,input().split()))
        l,r = l-1,r-1
        if same(l,r):
            if d != diff(l,r):
                print('No')
                exit()
        else:
            unite(l,r,d)
    print('Yes')
            
if __name__ == '__main__':
    main()
# Original solution
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, tan, asin, acos, atan, radians, degrees, log2, gcd
from itertools import accumulate, permutations, combinations, combinations_with_replacement, product, groupby
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left, insort, insort_left
from heapq import heappush, heappop
from functools import reduce
def input(): return sys.stdin.readline().strip()
def INT(): return int(eval(input()))
def MAP(): return list(map(int, input().split()))
def LIST(): return list(map(int, input().split()))
def TUPLE(): return tuple(map(int, input().split()))
def ZIP(n): return list(zip(*(MAP() for _ in range(n))))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7 
#mod = 998244353
from decimal import *
#import numpy as np
#decimal.getcontext().prec = 10

N, M = MAP()
LRD = [LIST() for _ in range(M)]

graph = [[] for _ in range(N)]
for L, R, D in LRD:
	graph[L-1].append((R-1, D))
	graph[R-1].append((L-1, -D))

check = [1]*N
i = 0
while i < N:
	while check[i] == 0:
		i += 1
		if i == N:
			print("Yes")
			exit()

	check[i] = 0
	dis = defaultdict(int)
	dis[i] = 0
	q = deque([i])
	while q:
		p = q.popleft()
		for v, dist in graph[p]:
			if check[v] == 1:
				check[v] = 0
				dis[v] = dis[p] + dist
				q.append(v)
			if check[v] == 0 and dis[v] != dis[p] + dist:
				print("No")
				exit()

# Optimized solution
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, tan, asin, acos, atan, radians, degrees, log2, gcd
from itertools import accumulate, permutations, combinations, combinations_with_replacement, product, groupby
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left, insort, insort_left
from heapq import heappush, heappop
from functools import reduce
def input(): return sys.stdin.readline().strip()
def INT(): return int(eval(input()))
def MAP(): return list(map(int, input().split()))
def LIST(): return list(map(int, input().split()))
def TUPLE(): return tuple(map(int, input().split()))
def ZIP(n): return list(zip(*(MAP() for _ in range(n))))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7 
#mod = 998244353
from decimal import *
#import numpy as np
#decimal.getcontext().prec = 10

N, M = MAP()
LRD = [LIST() for _ in range(M)]

graph = [[] for _ in range(N)]
for L, R, D in LRD:
	graph[L-1].append((R-1, D))
	graph[R-1].append((L-1, -D))

check = [1]*N
i = 0
while 1:
	while check[i] == 0:
		i += 1
		if i == N:
			print("Yes")
			exit()

	check[i] = 0
	dis = defaultdict(int)
	dis[i] = 0
	q = deque([i])
	while q:
		p = q.popleft()
		for v, dist in graph[p]:
			if check[v] == 1:
				check[v] = 0
				dis[v] = dis[p] + dist
				q.append(v)
			if check[v] == 0 and dis[v] != dis[p] + dist:
				print("No")
				exit()
# Original solution
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, tan, asin, acos, atan, radians, degrees, log2, gcd
from itertools import accumulate, permutations, combinations, combinations_with_replacement, product, groupby
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left, insort, insort_left
from heapq import heappush, heappop
from functools import reduce
def input(): return sys.stdin.readline().strip()
def INT(): return int(eval(input()))
def MAP(): return list(map(int, input().split()))
def LIST(): return list(map(int, input().split()))
def TUPLE(): return tuple(map(int, input().split()))
def ZIP(n): return list(zip(*(MAP() for _ in range(n))))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7 
#mod = 998244353
from decimal import *
#import numpy as np
#decimal.getcontext().prec = 10

N, M = MAP()
LRD = [LIST() for _ in range(M)]

graph = [[] for _ in range(N)]
for L, R, D in LRD:
	graph[L-1].append((R-1, D))
	graph[R-1].append((L-1, -D))

check = [1]*N
i = 0
while 1:
	while check[i] == 0:
		i += 1
		if i == N:
			print("Yes")
			exit()

	check[i] = 0
	dis = defaultdict(int)
	dis[i] = 0
	q = deque([i])
	while q:
		p = q.popleft()
		for v, dist in graph[p]:
			if check[v] == 1:
				check[v] = 0
				dis[v] = dis[p] + dist
				q.append(v)
			if check[v] == 0 and dis[v] != dis[p] + dist:
				print("No")
				exit()


# Optimized solution
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, tan, asin, acos, atan, radians, degrees, log2, gcd
from itertools import accumulate, permutations, combinations, combinations_with_replacement, product, groupby
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left, insort, insort_left
from heapq import heappush, heappop
from functools import reduce
def input(): return sys.stdin.readline().strip()
def INT(): return int(eval(input()))
def MAP(): return list(map(int, input().split()))
def LIST(): return list(map(int, input().split()))
def TUPLE(): return tuple(map(int, input().split()))
def ZIP(n): return list(zip(*(MAP() for _ in range(n))))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7 
#mod = 998244353
from decimal import *
#import numpy as np
#decimal.getcontext().prec = 10

N, M = MAP()
 
graph = defaultdict(list)
for _ in range(M):
	L, R, D = MAP()
	graph[L-1].append((R-1, D))
	graph[R-1].append((L-1, -D))
 
num = [None]*N

for i in range(N):
	if num[i] != None:
		continue
	q = deque([i])
	num[i] = 0
	while q:
		n = q.popleft()
		for node, weight in graph[n]:
			if num[node] == None:
				num[node] = num[n] + weight
				q.append(node)
			elif num[node] != num[n] + weight:
				print("No")
				exit()

else:
	print("Yes")
# Original solution
from collections import deque
N, M = list(map(int, input().split()))
L = []
R = []
D = []
G = [[] for _ in range(N+1)]
for _ in range(M):
    tmpl, tmpr, tmpd = list(map(int, input().split()))
    # if tmpl > tmpr:
    #    tmpl, tmpr = tmpr, tmpl
    #    tmpd *= -1
    L.append(tmpl)
    R.append(tmpr)
    D.append(tmpd)
    G[tmpl].append((tmpr, tmpd))
    G[tmpr].append((tmpl, -tmpd))

field = [None] * (N+1)


def dfs(i):
    q = deque()
    q.append(i)
    field[i] = 0
    used = [False]*(N+1)
    used[i] = True
    while q:
        tmp = q.pop()
        for elem in G[tmp]:
            if used[elem[0]]:
                if field[elem[0]] is not None:
                    if field[elem[0]] != field[tmp]+elem[1]:
                        return False
                continue
            q.append(elem[0])
            if field[elem[0]] == None:
                field[elem[0]] = field[tmp]+elem[1]
                used[elem[0]] = True
            else:
                if field[elem[0]] != field[tmp]+elem[1]:
                    return False

    return True


for i in range(1, N+1):
    if field[i] == None:
        if not dfs(i):
            print('No')
            exit()
print('Yes')


# Optimized solution
from collections import deque
N, M = list(map(int, input().split()))
#L = []
#R = []
#D = []
G = [[] for _ in range(N+1)]
for _ in range(M):
    tmpl, tmpr, tmpd = list(map(int, input().split()))
    # L.append(tmpl)
    # R.append(tmpr)
    # D.append(tmpd)
    G[tmpl].append((tmpr, tmpd))
    G[tmpr].append((tmpl, -tmpd))

field = [None] * (N+1)


def dfs(i):
    q = deque()
    q.append(i)
    field[i] = 0
    #used = [False]*(N+1)
    #used[i] = True
    while q:
        tmp = q.pop()
        for elem in G[tmp]:
            if field[elem[0]] is not None:
                if field[elem[0]] != field[tmp]+elem[1]:
                    return False
                continue
            else:
                q.append(elem[0])
                field[elem[0]] = field[tmp]+elem[1]

            # if used[elem[0]]:
            #    if field[elem[0]] is not None:
            #        if field[elem[0]] != field[tmp]+elem[1]:
            #            return False
            #    continue
            # q.append(elem[0])
            # if field[elem[0]] == None:
            #    field[elem[0]] = field[tmp]+elem[1]
            #    used[elem[0]] = True
            # else:
            #    if field[elem[0]] != field[tmp]+elem[1]:
            #        return False

    return True


for i in range(1, N+1):
    if field[i] == None:
        if not dfs(i):
            print('No')
            exit()
print('Yes')
# Original solution
from collections import deque
N, M = list(map(int, input().split()))
#L = []
#R = []
#D = []
G = [[] for _ in range(N+1)]
for _ in range(M):
    tmpl, tmpr, tmpd = list(map(int, input().split()))
    # L.append(tmpl)
    # R.append(tmpr)
    # D.append(tmpd)
    G[tmpl].append((tmpr, tmpd))
    G[tmpr].append((tmpl, -tmpd))

field = [None] * (N+1)


def dfs(i):
    q = deque()
    q.append(i)
    field[i] = 0
    #used = [False]*(N+1)
    #used[i] = True
    while q:
        tmp = q.pop()
        for elem in G[tmp]:
            if field[elem[0]] is not None:
                if field[elem[0]] != field[tmp]+elem[1]:
                    return False
                continue
            else:
                q.append(elem[0])
                field[elem[0]] = field[tmp]+elem[1]

            # if used[elem[0]]:
            #    if field[elem[0]] is not None:
            #        if field[elem[0]] != field[tmp]+elem[1]:
            #            return False
            #    continue
            # q.append(elem[0])
            # if field[elem[0]] == None:
            #    field[elem[0]] = field[tmp]+elem[1]
            #    used[elem[0]] = True
            # else:
            #    if field[elem[0]] != field[tmp]+elem[1]:
            #        return False

    return True


for i in range(1, N+1):
    if field[i] == None:
        if not dfs(i):
            print('No')
            exit()
print('Yes')


# Optimized solution
from collections import deque
N, M = list(map(int, input().split()))
G = [[] for _ in range(N+1)]
for _ in range(M):
    tmpl, tmpr, tmpd = list(map(int, input().split()))
    G[tmpl].append((tmpr, tmpd))
    G[tmpr].append((tmpl, -tmpd))

field = [None] * (N+1)


def dfs(i):
    q = deque()
    q.append(i)
    field[i] = 0
    while q:
        tmp = q.pop()
        for elem in G[tmp]:
            if field[elem[0]] is not None:
                if field[elem[0]] != field[tmp]+elem[1]:
                    return False
                continue
            else:
                q.append(elem[0])
                field[elem[0]] = field[tmp]+elem[1]
    return True


for i in range(1, N+1):
    if field[i] is None:
        if not dfs(i):
            print('No')
            exit()
print('Yes')