#include <bits/stdc++.h>
using namespace std;
template <typename T>
T gcd(T a, T b) {
  return b == 0 ? a : gcd(b, a % b);
}
template <typename T>
T lcm(T a, T b) {
  return a / gcd(a, b) * b;
}
template <typename T>
T ext_gcd(T a, T b, T& first, T& second) {
  if (b == 0) {
    first = 1, second = 0;
    return a;
  }
  T d = ext_gcd(b, a % b, second, first);
  second -= first * (a / b);
  return d;
}
template <typename T>
T inverse(T a, T n) {
  T first, second;
  T t = ext_gcd(a, n, first, second);
  if (t != 1) return -1;
  return (first % n + n) % n;
}
template <typename T>
T Q_mul(T a, T b, T Mod) {
  T ret;
  for (ret = 0; b; b >>= 1, a = (a + a) % Mod)
    if (b & 1) ret = (ret + a) % Mod;
  return ret;
}
template <typename T>
T quick_pow_mod(T a, T b, T Mod) {
  T ret;
  for (ret = 1; b; b >>= 1, (a *= a) %= Mod)
    if (b & 1) (ret *= a) %= Mod;
  return ret;
}
template <typename T>
T quick_pow(T a, T b) {
  T ret;
  for (ret = 1; b; b >>= 1, a *= a)
    if (b & 1) ret *= a;
  return ret;
}
double combination(int n, int r) {
  if (r < n - r) return combination(n, n - r);
  double s = 1.0;
  for (int i = 1; i <= int(n - r); ++i) s *= (r + i), s /= i;
  return s;
}
template <typename T>
inline void read(T& v) {
  T ret = 0, sgnv = 1;
  char p;
  while (!isdigit(p = getchar()))
    if (p == '-') sgnv = -1;
  do ret = (ret << 3) + (ret << 1) + p - '0';
  while (isdigit(p = getchar()));
  v = sgnv * ret;
}
const long long maxn = 1e6;
struct Edge {
  int u, v, next;
  long long p, g, l;
} edge[20000 + 5];
int head[100 + 5], seq[100 + 5], degree[100 + 5], cnt;
long long num[100 + 5];
bool vis[100 + 5];
inline void addEdge(int& u, int& v, long long g, long long l) {
  ++degree[u], ++degree[v];
  edge[cnt].v = v, edge[cnt].g = g, edge[cnt].l = l, edge[cnt].p = g * l,
  edge[cnt].next = head[u], head[u] = cnt++;
  edge[cnt].v = u, edge[cnt].g = g, edge[cnt].l = l, edge[cnt].p = g * l,
  edge[cnt].next = head[v], head[v] = cnt++;
}
bool cmp(int u, int v) { return degree[u] > degree[v]; }
bool dfs(int u) {
  int v;
  for (int i = head[u]; ~i; i = edge[i].next) {
    if (!vis[v = edge[i].v]) {
      if (edge[i].p % num[u] != 0) return false;
      num[v] = edge[i].p / num[u], vis[v] = true;
      if (!dfs(v)) {
        return false;
      }
    } else if (num[u] * num[v] != edge[i].p ||
               lcm(num[u], num[v]) != edge[i].l ||
               gcd(num[u], num[v]) != edge[i].g)
      return false;
  }
  return true;
}
bool solve(int u) {
  long long g = 0;
  for (int i = head[u]; ~i; i = edge[i].next) g = gcd(g, edge[i].p);
  if (g == 0) {
    num[u] = 1;
    return true;
  }
  for (long long i = 1; i * i <= g; ++i)
    if (g % i == 0) {
      if (num[u] = i, memset(vis, 0, sizeof(vis)), vis[u] = true, dfs(u))
        return true;
      if (g / i <= maxn &&
          (num[u] = g / i, memset(vis, 0, sizeof(vis)), vis[u] = true, dfs(u)))
        return true;
    }
  return false;
}
int main() {
  int n, m, u, v;
  bool ok = true;
  long long g, l;
  memset(head, -1, sizeof(head)), read(n), read(m);
  while (m--) read(u), read(v), read(g), read(l), addEdge(u, v, g, l);
  for (int i = 0; i < int(n); ++i) seq[i] = i + 1;
  sort(seq, seq + n, cmp);
  for (int i = 0; i < int(n); ++i)
    if (!vis[seq[i]] && !solve(seq[i])) {
      ok = false;
      break;
    }
  puts(ok ? "YES" : "NO");
  if (ok)
    for (int i = 1; i <= int(n); ++i)
      printf("%I64d", num[i]), i == n ? 0 : putchar(' ');
  return 0;
}
