Problem:
 Score : 400 points    Problem Statement There are N people standing on the x -axis.
Let the coordinate of Person i be x_i .
For every i , x_i is an integer between 0 and 10^9 (inclusive).
It is possible that more than one person is standing at the same coordinate.  You will given M pieces of information regarding the positions of these people.
The i -th piece of information has the form (L_i, R_i, D_i) .
This means that Person R_i is to the right of Person L_i by D_i units of distance, that is, x_{R_i} - x_{L_i} = D_i holds.  It turns out that some of these M pieces of information may be incorrect.
Determine if there exists a set of values (x_1, x_2, ..., x_N) that is consistent with the given pieces of information.      Constraints  1 \leq N \leq 100  000  0 \leq M \leq 200  000  1 \leq L_i, R_i \leq N ( 1 \leq i \leq M )  0 \leq D_i \leq 10  000 ( 1 \leq i \leq M )  L_i \neq R_i ( 1 \leq i \leq M )  If i \neq j , then (L_i, R_i) \neq (L_j, R_j) and (L_i, R_i) \neq (R_j, L_j) .  D_i are integers.         Input Input is given from Standard Input in the following format:  N  M  L_1  R_1  D_1  L_2  R_2  D_2  :  L_M  R_M  D_M       Output If there exists a set of values (x_1, x_2, ..., x_N) that is consistent with all given pieces of information, print Yes ; if it does not exist, print No .        Sample Input 1 3 3
1 2 1
2 3 1
1 3 2      Sample Output 1 Yes  Some possible sets of values (x_1, x_2, x_3) are (0, 1, 2) and (101, 102, 103) .       Sample Input 2 3 3
1 2 1
2 3 1
1 3 5      Sample Output 2 No  If the first two pieces of information are correct, x_3 - x_1 = 2 holds, which is contradictory to the last piece of information.       Sample Input 3 4 3
2 1 1
2 3 5
3 4 2      Sample Output 3 Yes       Sample Input 4 10 3
8 7 100
7 9 100
9 8 100      Sample Output 4 No       Sample Input 5 100 0      Sample Output 5 Yes

Solution (Python):
n, m = 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 = 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")

Solution (Python):
import sys
stdin = sys.stdin
 
sys.setrecursionlimit(10**5) 
 
def li(): return map(int, stdin.readline().split())
def li_(): return map(lambda x: int(x)-1, stdin.readline().split())
def lf(): return map(float, stdin.readline().split())
def ls(): return stdin.readline().split()
def ns(): return stdin.readline().rstrip()
def lc(): return list(ns())
def ni(): return int(stdin.readline())
def nf(): return float(stdin.readline())

n,m = li()

graph = [[] for _ in range(n)]
for _ in range(m):
    l,r,d = li()
    l -= 1
    r -= 1
    graph[l].append((d,r))
    graph[r].append((-d,l))
    
searched = [False]*n
dist = [float("inf") for _ in range(n)]

exist = True
for i in range(n):
    if not searched[i]:
        dist[i] = 0
        searched[i] = True
        stack = [(0,i)]
        
        while stack:
            cost, cur = stack.pop()
            for nex_cost, nex_node in graph[cur]:
                if searched[nex_node]:
                    if cost + nex_cost != dist[nex_node]:
                        exist = False
                        
                else:
                    stack.append((cost+nex_cost, nex_node))
                    dist[nex_node] = cost + nex_cost
                    searched[nex_node] = True
                    


print("Yes") if exist else print("No")

Solution (Python):
import sys
stdin = sys.stdin
 
sys.setrecursionlimit(10**5) 
 
def li(): return map(int, stdin.readline().split())
def li_(): return map(lambda x: int(x)-1, stdin.readline().split())
def lf(): return map(float, stdin.readline().split())
def ls(): return stdin.readline().split()
def ns(): return stdin.readline().rstrip()
def lc(): return list(ns())
def ni(): return int(stdin.readline())
def nf(): return float(stdin.readline())

n,m = li()

graph = [[] for _ in range(n)]
for _ in range(m):
    l,r,d = li()
    l -= 1
    r -= 1
    graph[l].append((d,r))
    graph[r].append((-d,l))
    
searched = [False]*n
dist = [float("inf") for _ in range(n)]

exist = True
for i in range(n):
    if not searched[i]:
        dist[i] = 0
        searched[i] = True
        stack = [(0,i)]
        
        while stack:
            cost, cur = stack.pop()
            for nex_cost, nex_node in graph[cur]:
                if searched[nex_node]:
                    if cost + nex_cost != dist[nex_node]:
                        exist = False
                        
                else:
                    stack.append((cost+nex_cost, nex_node))
                    dist[nex_node] = cost + nex_cost
                    searched[nex_node] = True
                    
if exist:
    print("Yes")
else:
    print("No")

Solution (Python):
N,M = map(int,input().split())
src = [tuple(map(int,input().split())) for i in range(M)]
es = [{} for i in range(N)]
for l,r,d in src:
    es[l-1][r-1] = d
    es[r-1][l-1] = -d

dist = [None] * N
for i in range(N):
    if dist[i] is not None: continue
    dist[i] = 0
    stack = [i]
    while stack:
        v = stack.pop()
        for to,d in es[v].items():
            if dist[to] is not None:
                if dist[to] != dist[v]+d:
                    print('No')
                    exit()
                continue
            dist[to] = dist[v]+d
            stack.append(to)
print('Yes')

Solution (Python):
import sys

N,M=map(int,input().split())
LRD=[list(map(int,input().split())) for i in range(M)]



Group=[(i,0) for i in range(N+1)]
 
def find(x):
    ANS=0
    while Group[x][0] != x:
        ANS+=Group[x][1]
        x=Group[x][0]
        
    return (x,ANS)

def Union(x,y,d):
    if x>y:
        x,y,d=y,x,-d
    if find(x)[0]!=find(y)[0]:
        reach=min(find(x)[0],find(y)[0])

        if find(x)[0]!=reach:
            
            
            
            
            Group[find(x)[0]]=(reach,find(y)[1]-d-find(x)[1])


        else:
            
            
            
            
            Group[find(y)[0]]=(reach,find(x)[1]+d-find(y)[1])



    else:
        if find(x)[1]+d != find(y)[1]:
            
            return False

    Group[y]=(x,d)
    return True

for l,r,d in LRD:
    
    if Union(l,r,d)==False:
        print("No")
        sys.exit()

print("Yes")

Solution (Python):
import sys
stdin = sys.stdin
 
sys.setrecursionlimit(10**5) 
 
def li(): return map(int, stdin.readline().split())
def li_(): return map(lambda x: int(x)-1, stdin.readline().split())
def lf(): return map(float, stdin.readline().split())
def ls(): return stdin.readline().split()
def ns(): return stdin.readline().rstrip()
def lc(): return list(ns())
def ni(): return int(stdin.readline())
def nf(): return float(stdin.readline())

class WeightedUnionFind:
    def __init__(self, node:int) -> None:
        self.n = node
        self.par = [i for i in range(self.n)]
        self.rank = [0 for i in range(self.n)]
        self.diff_weight = [0 for i in range(self.n)]
        
    
    def find(self, x:int) -> int:
        if x == self.par[x]:
            return x
        else:
            r = self.find(self.par[x])
            self.diff_weight[x] += self.diff_weight[self.par[x]]
            self.par[x] = r
            return self.par[x]
        
    
    def weight(self, x:int) -> int:
        self.find(x)
        return self.diff_weight[x]
        
    
    def unite(self, x:int, y:int, w:int) -> bool:
        if self.isSame(x,y):
            return False
        
        w += self.weight(x)
        w -= self.weight(y)
        
        rx = self.find(x)
        ry = self.find(y)
        
        if self.rank[rx] < self.rank[ry]:
            rx, ry = ry, rx
            w = -w

        self.par[ry] = self.par[rx]
        self.diff_weight[ry] = w
        
        if self.rank[rx] == self.rank[ry]:
            self.rank[rx] += 1
                
        return True
                
    
    def isSame(self, x:int, y:int) -> bool:
        return self.find(x) == self.find(y)
    
    def diff(self, x:int, y:int) -> int:
        if self.isSame(x,y):
            return self.weight(y)-self.weight(x)
        else:
            raise ValueError("xとyは同じ木に属していません")


n,m = li()

lrd = []
for _ in range(m):
    l,r,d = li()
    l -= 1
    r -= 1
    lrd.append((l,r,d))
 
exist = True

wuf = WeightedUnionFind(n)

for l,r,d in lrd:
    wuf.unite(l,r,d)
    if wuf.diff(l,r) != d:
        exist = False
        break
    
if exist:
    print("Yes")
else:
    print("No")

Solution (Python):
import sys
stdin = sys.stdin
 
sys.setrecursionlimit(10**5) 
 
def li(): return map(int, stdin.readline().split())
def li_(): return map(lambda x: int(x)-1, stdin.readline().split())
def lf(): return map(float, stdin.readline().split())
def ls(): return stdin.readline().split()
def ns(): return stdin.readline().rstrip()
def lc(): return list(ns())
def ni(): return int(stdin.readline())
def nf(): return float(stdin.readline())

class WeightedUnionFind:
    def __init__(self, node:int) -> None:
        self.n = node
        self.par = [i for i in range(self.n)]
        self.rank = [0 for i in range(self.n)]
        self.diff_weight = [0 for i in range(self.n)]
        
    
    def find(self, x:int) -> int:
        if x == self.par[x]:
            return x
        else:
            r = self.find(self.par[x])
            self.diff_weight[x] += self.diff_weight[self.par[x]]
            self.par[x] = r
            return self.par[x]
        
    
    def weight(self, x:int) -> int:
        self.find(x)
        return self.diff_weight[x]
        
    
    def unite(self, x:int, y:int, w:int) -> bool:
        if self.isSame(x,y):
            return False
        
        w += self.weight(x)
        w -= self.weight(y)
        
        rx = self.find(x)
        ry = self.find(y)
        
        if self.rank[rx] < self.rank[ry]:
            rx, ry = ry, rx
            w = -w

        self.par[ry] = self.par[rx]
        self.diff_weight[ry] = w
        
        if self.rank[rx] == self.rank[ry]:
            self.rank[rx] += 1
                
        return True
                
    
    def isSame(self, x:int, y:int) -> bool:
        return self.find(x) == self.find(y)
    
    def diff(self, x:int, y:int) -> int:
        if self.isSame(x,y):
            return self.weight(y)-self.weight(x)
        else:
            raise ValueError("xとyは同じ木に属していません")


n,m = li()

lrd = []
for _ in range(m):
    l,r,d = li()
    l -= 1
    r -= 1
    lrd.append((l,r,d))
 
exist = True

wuf = WeightedUnionFind(n)

for l,r,d in lrd:
    wuf.unite(l,r,d)
    if wuf.diff(l,r) != d:
        exist = False
        break
    
if exist:
    print("Yes")
else:
    print("No")

Solution (Python):
import queue
inf = float('inf')
N,M = map(int,input().split())
edge = {}
for i in range(N):
    edge[i] = {}
for i in range(M):
    L,R,D = map(int,input().split())
    L -= 1
    R -= 1
    edge[L][R] = D
    edge[R][L] = -D

x = [inf for i in range(N)]

def bfs(n):
    que = queue.Queue()
    que.put(n)
    x[n] = 0
    ans = True
    while que.qsize():
        L = que.get()
        for R in edge[L]:
            if x[R] != inf:
                if x[R] != x[L]+edge[L][R]:
                    ans = False
            else:
                x[R] = x[L]+edge[L][R]
                que.put(R)
    return ans
for n in range(N):
    if x[n] == inf:
        ans = bfs(n)
        if not ans:
            break

if ans:
    print('Yes')
else:
    print('No')

Solution (Python):


import sys


input = sys.stdin.readline


def inpl(): return list(map(int, input().split()))



class UnionFind:
    __slots__ = ['nodes', 'weight']

    def __init__(self, size: int) -> None:
        self.nodes = [-1] * size  
        self.weight = [0] * size  

    
    def find(self, x: int) -> int:
        if self.nodes[x] < 0:
            return x
        else:
            parent = self.find(self.nodes[x])
            self.weight[x] += self.weight[self.nodes[x]]
            self.nodes[x] = parent
            return parent

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    
    
    
    def relate(self, x: int, y: int, w: int) -> bool:
        root_x = self.find(x)
        root_y = self.find(y)
        if root_x == root_y:
            
            if self.weight[x] - self.weight[y] == w:
                return False
            raise ValueError
        else:
            rank_x = -self.nodes[root_x]
            rank_y = -self.nodes[root_y]
            if rank_x < rank_y:
                self.nodes[root_x] = root_y
                self.weight[root_x] = w + self.weight[y] - self.weight[x]
            else:
                self.nodes[root_y] = root_x
                self.weight[root_y] = -w + self.weight[x] - self.weight[y]

                if rank_x == rank_y:
                    self.nodes[root_x] += -1
            return True

    
    
    
    
    
    
    
    
    
    
    
    
    
    


N, M = inpl()
uf = UnionFind(N)
relate = uf.relate
try:
    for i in range(M):
        l, r, d = inpl()
        relate(l - 1, r - 1, d)
    else:
        print('Yes')
except ValueError:
    print('No')

Solution (Python):


import sys


input = sys.stdin.readline


def inpl(): return list(map(int, input().split()))



class UnionFind:
    __slots__ = ['nodes', 'weight']

    def __init__(self, size: int) -> None:
        self.nodes = [-1] * size
        self.weight = [0] * size

    
    def find(self, x: int) -> int:
        if self.nodes[x] < 0:
            return x
        else:
            parent = self.find(self.nodes[x])
            self.weight[x] += self.weight[self.nodes[x]]
            self.nodes[x] = parent
            return parent

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    
    
    
    def relate(self, x: int, y: int, w: int) -> bool:
        root_x = self.find(x)
        root_y = self.find(y)
        if root_x == root_y:  
            
            
            
            if self.weight[x] - self.weight[y] == w:
                return False
            raise ValueError
        else:
            rank_x = -self.nodes[root_x]
            rank_y = -self.nodes[root_y]
            if rank_x < rank_y:
                self.nodes[root_x] = root_y
                self.weight[root_x] = w + self.weight[y] - self.weight[x]
            else:
                self.nodes[root_y] = root_x
                self.weight[root_y] = -w + self.weight[x] - self.weight[y]

                if rank_x == rank_y:
                    self.nodes[root_x] += -1
            return True

    
    def get_tree(self) -> dict:
        tree = {}
        for i, node in enumerate(self.nodes):
            if node < 0:
                if i not in tree.keys():
                    tree[i] = []
            else:
                if self.find(node) in tree.keys():
                    tree[self.find(node)].append(i)
                else:
                    tree[self.find(node)] = [i]

        return tree


N, M = inpl()
uf = UnionFind(N)
relate = uf.relate
try:
    for i in range(M):
        l, r, d = inpl()
        relate(l - 1, r - 1, d)
    else:
        print('Yes')
except ValueError:
    print('No')

Solution (Python):
n, m = map(int, input().split())
lrd = []

MAX = 999999

p = [[] for _ in range(n)]
for i in range(m):
    l, r, d = map(int, input().split())
    lrd.append([l-1, r-1, d, 0])
    p[l-1].append(i)
    p[r-1].append(i)

if m <= 1:
    print('Yes')
    exit()

a = [MAX for _ in range(n)]


target = lrd[0][0]
a[target] = 0
temp = [target]
t = 0
while 1:
    next = []
    for x in temp:
        for y in p[x]:
            if lrd[y][3] == 1:
                continue

            if lrd[y][0] == x:
                t = lrd[y][1]
                d = a[x] + lrd[y][2]
            else:
                t = lrd[y][0]
                d = a[x] - lrd[y][2]

            lrd[y][3] = 1

            if a[t] == MAX:
                a[t] = d
                next.append(t)
            elif a[t] != d:
                print('No')
                exit()

    if len(next) == 0:
        check = 0
        for i in range(m):
            if lrd[i][3] == 0:
                check = 1
                target = lrd[i][0]
                break

        if check == 1:
            temp = [target]
            a[target] = 0
            continue
        else:
            break

    temp = [] + list(set(next))

print('Yes')

Solution (Python):
N, M = map(int, input().split())


class WeightedUnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n)]
        self.rank = [0] * n
        
        self.weight = [0] * n

    
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            y = self.find(self.par[x])
            
            self.weight[x] += self.weight[self.par[x]]
            self.par[x] = y
            return y

    
    def weighting(self, x):
        self.find(x)
        return self.weight[x]

    
    def union(self, x, y, w):
        rx = self.find(x)
        ry = self.find(y)
        
        if self.rank[rx] < self.rank[ry]:
            self.par[rx] = ry
            self.weight[rx] = w - self.weight[x] + self.weight[y]
        
        else:
            self.par[ry] = rx
            self.weight[ry] = -w - self.weight[y] + self.weight[x]
            if self.rank[rx] == self.rank[ry]:
                self.rank[rx] += 1

    
    def same(self, x, y):
        return self.find(x) == self.find(y)

    
    def diff(self, x, y):
        return self.weight[x] - self.weight[y]


WUF = WeightedUnionFind(N)
for i in range(M):
    l, r, d = map(int, input().split())
    l, r = l-1, r-1
    if WUF.same(l, r):
        if WUF.diff(l, r) != d:
            print("No")
            exit()
    else:
        WUF.union(l, r, d)

print("Yes")

Solution (Python):
n,m = map(int,input().split())
g = [[] for i in range(n)]
for i in range(m):
  l,r,d = map(int,input().split())
  g[l-1].append([r-1,d])
  g[r-1].append([l-1,-d])
syo = [-1] * n
que = []
for i in range(n):
  if syo[i] != -1:
    continue
  syo[i] = 0
  que.append(i)
  while que:
    x = que.pop()
    for j,jb in g[x]:
      if (syo[j] != syo[x]+jb and syo[j] != -1):
        print("No")
        exit()
      syo[j] = syo[x] + jb
      que.append(j)
    g[x] = []
print("Yes")

Solution (Python):
from collections import deque

n, m = list(map(int, input().split()))
paths = {}
for i in range(m):
    l, r, d = list(map(int, input().split()))
    if not l in paths.keys():
        paths[l] = [(r, d)]
    else:
        paths[l].append((r, d))
    if not r in paths.keys():
        paths[r] = [(l, -d)]
    else:
        paths[r].append((l, -d))
      
x = [None]*(n+1)
for i in range(1, n+1):
    if x[i] is None:
        x[i] = 0
        que = deque([i])
        while len(que) > 0:
            j = que.popleft()
            if not j in paths.keys():
                continue
            for k, d in paths[j]:
                if x[k] is None:
                    x[k] = x[j] + d
                    que.append(k)
                elif x[k] != x[j] + d:
                    print('No')
                    exit()

print('Yes')

Solution (Python):
from collections import deque

n, m = 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])

x = [None for i in range(n)]

def f():
    for i in range(n):
        if x[i] == None:
            x[i] = 0
            q = deque([i])
            while len(q):
                j = q.popleft()
                for k, d in graph[j]:
                    if x[k] == None:
                        q.append(k)
                        x[k] = x[j] + d
                    elif x[k] != x[j] + d:
                        return False
    return True

if f():
    print("Yes")
else:
    print("No")

Solution (Python):
I=lambda:map(int,input().split())
n,m=I()
r=range(n)
y=[[] for i in r]
z=[None for i in r]

for _ in [0]*m:
  i,j,k=I()
  y[i-1]+=[[j-1, k]]
  y[j-1]+=[[i-1,-k]]

for i in r:
  if z[i]==None:
    z[i]=0 
  q=[i]
  while q:
    p=q.pop()
    for j,k in y[p]:
      if z[j]==None:
        q+=[j]
        z[j]=z[p]+k
      elif z[j]!=z[p]+k:
        print("No")
        exit()
print("Yes")

Solution (Python):


from collections import defaultdict, Counter
from itertools import product, groupby, count, permutations, combinations
from math import pi, sqrt
from collections import deque
from bisect import bisect, bisect_left, bisect_right
from string import ascii_lowercase
from functools import lru_cache
import sys
sys.setrecursionlimit(10000)
INF = float("inf")
YES, Yes, yes, NO, No, no = "YES", "Yes", "yes", "NO", "No", "no"
dy4, dx4 = [0, 1, 0, -1], [1, 0, -1, 0]


def inside(y, x, H, W):
    return 0 <= y < H and 0 <= x < W


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

    x = [None] * N
    for k in range(N):
        if x[k] is not None:
            continue

        x[k] = 0
        que = deque()
        que.append(k)
        while len(que) != 0:
            i = que.popleft()

            for j, d in m[i]:
                if x[j] is None:
                    x[j] = x[i] + d
                    que.append(j)
                else:
                    if x[j] != x[i] + d:
                        print(No)
                        return

    print(Yes)


if __name__ == '__main__':
    main()

Solution (Python):
from sys import stdin
input = stdin.readline

class WeightedUnionFind:
    def __init__(self, node:int) -> None:
        self.n = node
        self.par = [i for i in range(self.n)]
        self.rank = [0 for i in range(self.n)]
        self.diff_weight = [0 for i in range(self.n)]
        
    
    def find(self, x:int) -> int:
        if x == self.par[x]:
            return x
        else:
            r = self.find(self.par[x])
            self.diff_weight[x] += self.diff_weight[self.par[x]]
            self.par[x] = r
            return self.par[x]
        
    
    def weight(self, x:int) -> int:
        self.find(x)
        return self.diff_weight[x]
        
    
    def unite(self, x:int, y:int, w:int) -> bool:
        if self.isSame(x,y):
            
            return False
        
        w += self.weight(x)
        w -= self.weight(y)
        
        rx = self.find(x)
        ry = self.find(y)
        
        if self.rank[rx] < self.rank[ry]:
            rx, ry = ry, rx
            w = -w

        self.par[ry] = self.par[rx]
        self.diff_weight[ry] = w
        
        if self.rank[rx] == self.rank[ry]:
            self.rank[rx] += 1
                
        return True
                
    
    def isSame(self, x:int, y:int) -> bool:
        return self.find(x) == self.find(y)
    
    def diff(self, x:int, y:int) -> int:
        if self.isSame(x,y):
            return self.weight(y)-self.weight(x)
        else:
            raise ValueError("xとyは同じ木に属していません")


  
N,M = map(int, input().split())
query = []
for _ in range(M):
    query.append(tuple(map(int, input().split())))
    
uf = WeightedUnionFind(N)
    
consistent = True
for l,r,d in query:
    l -= 1
    r -= 1
    if uf.isSame(l,r):
        if d != uf.diff(l,r):
            consistent = False
            break
    else:
        uf.unite(l,r,d)
        
if consistent:
    print("Yes")
else:
    print("No")

Solution (Python):
class WeightedUnionFind:
    def __init__(self, node:int) -> None:
        self.n = node
        self.par = [i for i in range(self.n)]
        self.rank = [0 for i in range(self.n)]
        self.diff_weight = [0 for i in range(self.n)]
        
    
    def find(self, x:int) -> int:
        if x == self.par[x]:
            return x
        else:
            r = self.find(self.par[x])
            self.diff_weight[x] += self.diff_weight[self.par[x]]
            self.par[x] = r
            return self.par[x]
        
    
    def weight(self, x:int) -> int:
        self.find(x)
        return self.diff_weight[x]
        
    
    def unite(self, x:int, y:int, w:int) -> bool:
        if self.isSame(x,y):
            
            return False
        
        w += self.weight(x)
        w -= self.weight(y)
        
        rx = self.find(x)
        ry = self.find(y)
        
        if self.rank[rx] < self.rank[ry]:
            rx, ry = ry, rx
            w = -w

        self.par[ry] = self.par[rx]
        self.diff_weight[ry] = w
        
        if self.rank[rx] == self.rank[ry]:
            self.rank[rx] += 1
                
        return True
                
    
    def isSame(self, x:int, y:int) -> bool:
        return self.find(x) == self.find(y)
    
    def diff(self, x:int, y:int) -> int:
        if self.isSame(x,y):
            return self.weight(y)-self.weight(x)
        else:
            raise ValueError("xとyは同じ木に属していません")


  
N,M = map(int, input().split())
query = []
for _ in range(M):
    query.append(tuple(map(int, input().split())))
    
uf = WeightedUnionFind(N)
    
consistent = True
for l,r,d in query:
    l -= 1
    r -= 1
    if uf.isSame(l,r):
        if d != uf.diff(l,r):
            consistent = False
            break
    else:
        uf.unite(l,r,d)
        
if consistent:
    print("Yes")
else:
    print("No")

Solution (Python):
n, m = map(int, input().split())

graph = [[] for _ in range(n)]


for _ in range(m):
    l, r, d = map(int, input().split())
    graph[l - 1].append(( d,r - 1))
    graph[r - 1].append((-d,l - 1))

INF = float("inf")
dist = [-INF]*n


for n in range(n):
    if dist[n] != -INF:
        continue
    else:
        stack = [n]
        dist[n] = 0
        
    
    while len(stack):
        cur = stack.pop()
        
        
        for cost, nex_node in graph[cur]:
            if dist[nex_node] != -INF:
                continue
            else:
                dist[nex_node] = dist[cur] + cost
                stack.append(nex_node)

def solve():
    for i in range(n):
        for d,node in graph[i]:
            if dist[node]-dist[i] != d:
                print("No")
                return 0
            
    print("Yes")
    return 0

solve()

Solution (Python):
from collections import deque

class MakeGraph:
    
    
    
    
    def __init__(self, node_num:int, isMat:bool) -> None:
        self.n = node_num
        self.isMat = isMat

        
        if self.isMat:
            INF = float("inf")
            self.graph = [[INF for _ in range(self.n)] for _ in range(self.n)]
    
        
        else:
            self.graph = [[] for _ in range(self.n)]

    
    
    
    def add_undr_edge_mat(self, frm:int, to:int, dist:int) -> None:
        self.graph[frm][to] = dist
        self.graph[to][frm] = dist
        
    def add_drct_edge_mat(self, frm:int, to:int, dist:int) -> None:
        self.graph[frm][to] = dist
        
    def add_undr_edge_lst(self, frm:int, to:int, dist:int) -> None:
        self.graph[frm].append((dist, to))
        self.graph[to].append((dist, frm))
        
    def add_drct_edge_lst(self, frm:int, to:int, dist:int) -> None:
        self.graph[frm].append((dist, to))

                
    
    def get_graph(self) -> list:
        return self.graph


class DfsAndBfs:
 
  
  
  
  @classmethod
  def dfs(cls, graph:list, node:int) -> list:
    
    INF = float("inf")
    dist = [-INF]*node  
    
    
    for n in range(node):
        if dist[n] != -INF:
            continue
        else:
            stack = [n]
            dist[n] = 0
            
        
        while len(stack):
            cur = stack.pop()
            
            
            for cost, nex_node in graph[cur]:
                if dist[nex_node] != -INF:
                    continue
                else:
                    dist[nex_node] = dist[cur] + cost
                    stack.append(nex_node)

    return dist
 
  
  
  
  
  @classmethod
  def bfs(cls, graph:list, node:int) -> list:
      
      INF = float("inf")
      dist = [-INF]*node

      
      for n in range(node):
          if dist[n] != -INF:
              continue
          else:
              que = deque([n])
              dist[n] = 0

          
          while len(que):
              cur = deque.popleft(que)

              
              for cost, nex_node in graph[cur]:
                  if dist[nex_node] != -INF:
                      continue
                  else:
                      dist[nex_node] = dist[cur] + cost
                      que.append(nex_node)

      return dist
  

N,M = map(int ,input().split())
LRD = []
for i in range(M):
    LRD.append(tuple(map(int ,input().split())))

graphMaker = MakeGraph(N, False)
add_edge = graphMaker.add_drct_edge_lst
for l,r,d in LRD:
    add_edge(l-1,r-1,d)
    add_edge(r-1,l-1,-d)
    
graph = graphMaker.get_graph()

dist = DfsAndBfs.bfs(graph, N)



consistent = True

for l,r,d in LRD:
    if dist[r-1] - dist[l-1] == d:
        continue
    else:
        consistent = False
        break

    
if consistent:
    print("Yes")
else:
    print("No")