#include <bits/stdc++.h>
using namespace std;
inline void pisz(int n) { printf("%d\n", n); }
template <typename T, typename TT>
ostream &operator<<(ostream &s, pair<T, TT> t) {
  return s << "(" << t.first << "," << t.second << ")";
}
template <typename T>
ostream &operator<<(ostream &s, vector<T> t) {
  for (int(i) = 0; (i) < (t.size()); ++(i)) s << t[i] << " ";
  return s;
}
vector<int> adj[102];
int num[102];
bool vis[102];
int gcd[102][102], lcm[102][102];
int gcdf(int a, int b) {
  if (b == 0) return a;
  return gcdf(b, a % b);
}
int lcmf(int a, int b) { return a / gcdf(a, b) * b; }
vector<vector<int> > podziel_na_skladowe(int n, vector<int> *adj) {
  vector<bool> vis(n + 1, 0);
  vector<vector<int> > wyn;
  for (int(i) = 1; (i) <= (n); ++(i)) {
    if (vis[i]) continue;
    vector<int> skladowa;
    deque<int> q;
    q.push_back(i);
    while (!q.empty()) {
      int v = q.front();
      q.pop_front();
      if (vis[v]) continue;
      vis[v] = 1;
      skladowa.push_back(v);
      for (int(j) = 0; (j) < ((int(adj[v].size()))); ++(j))
        q.push_back(adj[v][j]);
    }
    wyn.push_back(skladowa);
  }
  return wyn;
}
bool propagate(int v) {
  if (vis[v]) return true;
  vis[v] = 1;
  for (int(j) = 0; (j) < ((int(adj[v].size()))); ++(j)) {
    int w = adj[v][j];
    if (((long long)lcm[v][w] * gcd[v][w]) % num[v]) return false;
    int powinnobyc = (long long)lcm[v][w] * gcd[v][w] / num[v];
    if (lcmf(num[v], powinnobyc) != lcm[v][w] ||
        gcdf(num[v], powinnobyc) != gcd[v][w])
      return false;
    if (num[w] == -1)
      num[w] = powinnobyc;
    else if (num[w] != powinnobyc)
      return false;
    if (!propagate(w)) return false;
  }
  return true;
}
int main() {
  int(n), (m);
  scanf("%d %d", &(n), &(m));
  ;
  while (m--) {
    int(a), (b);
    scanf("%d %d", &(a), &(b));
    ;
    int(g), (l);
    scanf("%d %d", &(g), &(l));
    ;
    adj[a].push_back(b);
    adj[b].push_back(a);
    gcd[a][b] = gcd[b][a] = g;
    lcm[a][b] = lcm[b][a] = l;
    if (l % g) {
      printf("NO\n");
      return 0;
    }
  }
  vector<vector<int> > skladowe = podziel_na_skladowe(n, adj);
  for (int(k) = 0; (k) < ((int(skladowe.size()))); ++(k)) {
    vector<int> skladowa = skladowe[k];
    int poczw = skladowa[0];
    if ((int(skladowa.size())) == 1) {
      num[poczw] = 1;
      continue;
    }
    bool udalosie = 0;
    int poczg = gcd[poczw][adj[poczw][0]], poczl = lcm[poczw][adj[poczw][0]];
    for (int mnoznik = 1; mnoznik * poczg <= poczl; ++mnoznik) {
      if (poczl % (mnoznik * poczg)) continue;
      for (int(l) = 0; (l) < ((int(skladowa.size()))); ++(l)) {
        vis[skladowa[l]] = 0;
        num[skladowa[l]] = -1;
      }
      num[poczw] = mnoznik * poczg;
      if (propagate(poczw)) {
        udalosie = 1;
        break;
      }
    }
    if (!udalosie) {
      printf("NO\n");
      return 0;
    }
  }
  printf("YES\n");
  for (int(i) = 1; (i) <= (n); ++(i)) printf("%d ", num[i]);
}
