#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <limits>
#include <assert.h>
#include <algorithm>

#define DELAY -1
#define FAILED 0
#define SUCCESS 1

using namespace std;

struct equation {
  // x_a - x_b = c
  int a;
  int b;
  int c;
};

int n, m;

void print_equ(const equation& equ) {
  cout << "x_" << equ.a << " - ";
  cout << "x_" << equ.b << " = ";
  cout << equ.c << endl;
}

void print_equs(const vector<equation>& equs) {
  for(int i = 0; i < equs.size(); i++) {
    print_equ(equs[i]);
  }
}

// table[a] = x_a
// table[b] = x_b
// x_a - x_b = c
int apply(map<int, int>* table, const equation& equ) {
  auto ite_a = table->find(equ.a);
  auto ite_b = table->find(equ.b);
  bool find_a = ite_a != table->end();
  bool find_b = ite_b != table->end();
  if(find_a && find_b) {
    int c_desired = ite_a->second - ite_b->second;
    return equ.c == c_desired ? SUCCESS : FAILED;
  } else if(find_a) {
    // x_b = x_a - c
    int x_b = ite_a->second - equ.c;
    (*table)[equ.b] = x_b;
    return SUCCESS;
  } else if(find_b) {
    // x_a = x_b + c
    int x_a = ite_b->second + equ.c;
    (*table)[equ.a] = x_a;
    return SUCCESS;
  } else {
    return DELAY;
  }
}

vector<vector<equation> > group_by(const vector<equation>& equs) {
  vector<set<int> > connection(n + 1);
  for(int i = 0; i < equs.size(); i++) {
    int a = equs[i].a;
    int b = equs[i].b;
    connection[a].insert(i);
    connection[b].insert(i);
  }
  map<int, bool> visited;
  vector<vector<equation> > equs_by_group;
  queue<int> q;
  for(int i = 0; i < equs.size(); i++) {
    const equation& e = equs[i];
    int a = e.a;
    int b = e.b;
    //assert(visited[a] == visited[b]);
    if(visited[a])
      continue;
    vector<equation> equ_gr;
    equ_gr.push_back(e);
    q.push(a);
    q.push(b);
    while(!q.empty()) {
      int x = q.front();
      q.pop();
      if(visited[x])
        continue;
      visited[x] = true;
      for(auto &y : connection[x]) {
        const equation& e2 = equs[y];
        int other = e2.a == x ? e2.b : e2.a;
        if(y == i || visited[other])
          continue;
        equ_gr.push_back(e2);
        q.push(other);
      }
    }
    equs_by_group.push_back(equ_gr);
  }
  return equs_by_group;
}

void print_table(const map<int, int>& table) {
  for(auto &v : table) {
    cout << v.first << ":" << v.second << endl;
  }
}

bool update(const vector<equation>& equs, map<int, int>* table,
    vector<equation>* delayed) {
  for(int i = 0; i < equs.size(); i++) {
    switch(apply(table, equs[i])) {
      case DELAY:
        if(delayed != nullptr)
          delayed->push_back(equs[i]);
        break;
      case FAILED:
        return false;
      case SUCCESS:
        break;
      default:
        assert(false);
    }
  }
  return true;
}

bool solve_helper(const vector<equation>& equs) {
  //assert(equs.size() != 0);
  map<int, int> table;
  int a = equs[0].a;
  table[a] = 0;
  vector<equation> delayed;
  bool result = update(equs, &table, &delayed);
  if(!result)
    return false;
  if(delayed.size() == 0)
    return true;
  assert(false);
}

bool solve(const vector<equation>& equs) {
  const vector<vector<equation> >& equs_gr = group_by(equs);
  for(int i = 0; i < equs_gr.size(); i++) {
    const vector<equation>& connected = equs_gr[i];
    //print_equs(connected);
    if(!solve_helper(connected))
      return false;
  }
  return true;
}

int main() {
  cin >> n >> m;
  vector<equation> equs(m);
  int a, b, c;
  for(int i = 0; i < m; i++) {
    cin >> a >> b >> c;
    equs[i].a = a;
    equs[i].b = b;
    equs[i].c = c;
  }
  if(solve(equs))
    cout << "Yes" << endl;
  else
    cout << "No" << endl;
}

Measured memory_bytes: 36400