// Slower C++ solution:
#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <climits>

#include <cstring>

#include <string>

#include <vector>

#include <list>

#include <queue>

#include <stack>

#include <map>

#include <set>

#include <bitset>

#include <algorithm>

#include <functional>

#include <iomanip>

using namespace std;



#define LL long long

const int maxn = 100000 + 100;

struct Node {

    int pos;

    int dis;

    Node() {}

    Node(int p, int d) {

        pos = p;

        dis = d;

    }

};

int n, m, u, v, d;

bool flag;

int num[maxn], fa[maxn];

bool vis[maxn];

vector<Node> G[maxn];

queue<Node> que;



void Init() {

    flag = true;

    memset(vis, 0, sizeof(bool) * (n + 1));

    for(int i = 1; i <= n; ++i) {

        G[i].clear();

    }

    for(int i = 1; i <= n; ++i) {

        fa[i] = i;

    }

}



int Find(int x) {

    return (x == fa[x]? x: fa[x] = Find(fa[x]));

}



void unit(int x, int y) {

    int xx = Find(x);

    int yy = Find(y);

    fa[xx] = yy;

}



bool bfs(int x) {

    num[x] = 0;

    vis[x] = true;

    while(!que.empty()) {

        que.pop();

    }

    que.push(Node(x, 0));

    while(!que.empty()) {

        Node tmp = que.front();

        que.pop();

        int len = G[tmp.pos].size();

        for(int i = 0; i < len; ++i) {

            int pos = G[tmp.pos][i].pos;

            int d = G[tmp.pos][i].dis;

            if(!vis[pos]) {

                vis[pos] = true;

                num[pos] = tmp.dis + d;

                que.push(Node(pos, num[pos]));

            } else if(num[pos] != tmp.dis + d) {

                return false;

            }

        }

    }

    return true;

}



int main() {

    #ifdef LOCAL

        freopen("test.txt", "r", stdin);

//    freopen("out.txt", "w", stdout);

    #endif // LOCAL

    ios::sync_with_stdio(false);



    while(scanf("%d%d", &n, &m) != EOF) {

        Init();

        for(int i = 0; i < m; ++i) {

            scanf("%d%d%d", &u, &v, &d);

            G[u].push_back(Node(v, d));

            G[v].push_back(Node(u, -d));

            unit(v, u);

        }

        for(int i = 1; i <= n; ++i) {

            if(!vis[Find(i)]) {

                if(!bfs(Find(i))) {

                    flag = false;

                    break;

                }

            }

        }

        if(flag) {

            printf("Yes\n");

        } else {

            printf("No\n");

        }

    }



    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.5287686934361004x):
#include<iostream>

#include<cstdio>

#include<cmath>

#include<bits/stdc++.h>

using namespace std;

#define MAXN 400000+50

#define MAXM 400000+50

struct Edge{

    int from,to,dis,next;

}edge[MAXM];

#define inf 0x7fffffff

int head[MAXM];

int num=0;

void add(int u,int v,int dis)

{

    edge[++num].to=v,edge[num].dis=dis;

    edge[num].next=head[u];

    head[u]=num;

//    edge[++num].from=v,edge[num].to=u,edge[num].dis=dis;

}

bool vis[MAXN];

bool flag;

int pos[MAXN];

int rec[MAXN];

void dfs(int x)

{

    if(!flag) return;

    vis[x]=1;

    for(int i=head[x];i!=0;i=edge[i].next)

    {

        int t=pos[x]+edge[i].dis;

        if(pos[edge[i].to]==inf) pos[edge[i].to]=t,dfs(edge[i].to);

        else if(t!=pos[edge[i].to]) {

            flag=0;return;

        }

    }

}

int main()

{

    ios::sync_with_stdio(false);

    int n,m;

    cin>>n>>m;

    int cnt=0;

    for(int i=1;i<=m;++i)

    {

        int x,y,z;

        cin>>x>>y>>z;

        add(x,y,z);add(y,x,-z);

        pos[x]=pos[y]=inf;

        rec[++cnt]=x,rec[++cnt]=y;

    }

    sort(rec+1,rec+cnt+1);

    cnt=unique(rec+1,rec+n+1)-rec-1;

    for(int i=1;i<=cnt;++i)

    {

        if(!vis[rec[i]])

        {

            flag=1;

            pos[rec[i]]=0;

            dfs(rec[i]);

            if(!flag) {cout<<"No"<<endl;return 0;}

        }

    }

    puts("Yes");

}