#include <bits/stdc++.h>
using namespace std;
typedef list<pair<int, int> > nodesList;
struct polim {
  polim() {
    v[0] = v[1] = 0;
    inited = 0;
  }
  polim(int freeV, int x) {
    v[0] = freeV;
    v[1] = x;
    inited = true;
  }
  int v[2];
  bool inited;
  long double val;
  polim sub(int num) const { return polim(num - v[0], -v[1]); }
  polim operator+(const polim other) const {
    return polim(other.v[0] + v[0], other.v[1] + v[1]);
  }
  polim operator+=(const polim other) {
    this->v[0] += other.v[0];
    this->v[1] += other.v[1];
    return *this;
  }
  long double calc(long double x) { return val = v[0] + x * v[1]; }
};
void abortNoSol() {
  cout << "NO" << endl;
  exit(0);
}
vector<nodesList> G;
vector<polim> info;
long double value = 0;
int N, M;
vector<int> toChangeToValue;
bool doesXhaveValue = 0;
long double xVal;
set<long double> minDGetter;
long double SolveForXIFPossible(polim& n2, int sum) {
  if (n2.v[1]) {
    long double x = sum - n2.v[0];
    x /= n2.v[1];
    return x;
  }
  return 0;
}
void storeForTheSadCase(polim& p) {
  if (p.v[1]) {
    minDGetter.insert(SolveForXIFPossible(p, 0));
  }
}
void solveAll() {
  long double min = HUGE_VALL;
  for (long double i : minDGetter) {
    long double curr = 0;
    for (int j : toChangeToValue) {
      curr += abs(info[j].calc(i));
    }
    if (min > curr) {
      xVal = i;
      min = curr;
    }
  }
}
void compere(polim n2, int sum) {
  if (n2.v[1]) {
    long double x = sum - n2.v[0];
    x /= n2.v[1];
    if (!doesXhaveValue) {
      xVal = x;
      doesXhaveValue = true;
    } else if (xVal != x) {
      abortNoSol();
    }
  } else {
    if (n2.v[0] != sum) {
      abortNoSol();
    }
  }
}
void dfaFrom(int start) {
  polim& currP = info[start];
  toChangeToValue.push_back(start);
  storeForTheSadCase(currP);
  for (pair<int, int>& p : G[start]) {
    if (info[p.first].inited) {
      compere((info[p.first] + currP), p.second);
    } else {
      info[p.first] = currP.sub(p.second);
      dfaFrom(p.first);
    }
  }
}
void generalDfs() {
  for (int i = 0; i < N; i++) {
    if (!info[i].inited) {
      toChangeToValue.clear();
      doesXhaveValue = 0;
      xVal = 0;
      minDGetter.clear();
      info[i] = polim(0, 1);
      dfaFrom(i);
      if (!doesXhaveValue) {
        solveAll();
      }
      while (!toChangeToValue.empty()) {
        info[toChangeToValue.back()].calc(xVal);
        toChangeToValue.pop_back();
      }
    }
  }
}
int main() {
  int a, b, c;
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> N >> M;
  info.resize(N);
  G.resize(N);
  for (int i = 0; i < M; i++) {
    cin >> a >> b >> c;
    a--;
    b--;
    G[a].push_back(pair<int, int>(b, c));
    G[b].push_back(pair<int, int>(a, c));
  }
  generalDfs();
  cout << "YES" << endl;
  for (int i = 0; i < N; i++) {
    cout << info[i].val << " ";
  }
  cout << endl;
  return 0;
}
