#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
struct edge {
  int to, nxt, from;
} e[maxn << 1];
int head[maxn], cnt, ind[maxn];
void add(int x, int y) {
  e[++cnt].to = y;
  e[cnt].nxt = head[x];
  head[x] = cnt;
  ind[y]++;
  e[cnt].from = x;
}
struct edge2 {
  int to, nxt, val;
} e1[maxn << 1];
int head1[maxn], cnt1;
void add1(int x, int y, int z) {
  e1[++cnt1].to = y;
  e1[cnt1].nxt = head1[x];
  head1[x] = cnt1;
  e1[cnt1].val = z;
}
int n, m;
bool can[maxn];
int vis[maxn];
bool dfs(int x) {
  if (vis[x]) return can[x];
  if (x == n) return can[x] = 1;
  vis[x] = 1;
  for (int i = head[x]; i; i = e[i].nxt) {
    int t = e[i].to;
    if (dfs(t)) can[x] = 1;
  }
  return can[x];
}
bool init[maxn];
int d[maxn];
bool spfa(int s) {
  memset(vis, 0, sizeof(vis));
  memset(d, 0x3f, sizeof(d));
  queue<int> q;
  vis[s] = init[s] = 1, d[s] = 0;
  q.push(s);
  while (q.size()) {
    int x = q.front();
    q.pop();
    init[x] = 0;
    for (int i = head1[x]; i; i = e1[i].nxt) {
      int t = e1[i].to, v = e1[i].val;
      if (d[t] > d[x] + v) {
        d[t] = d[x] + v;
        if (!init[t]) {
          q.push(t), init[t] = 1, ++vis[t];
          if (vis[t] > n + 1) return 0;
        }
      }
    }
  }
  return 1;
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++) {
    int x, y;
    scanf("%d%d", &x, &y);
    add(x, y);
  }
  dfs(1);
  for (int i = 1; i <= m; i++) {
    int x = e[i].from, y = e[i].to;
    if (!(can[x] & can[y])) continue;
    add1(x, y, 2), add1(y, x, -1);
  }
  if (!can[1]) printf("No\n"), exit(0);
  if (spfa(1)) {
    printf("Yes\n");
    for (int i = 1; i <= m; i++) {
      int x = e[i].from, y = e[i].to;
      if (can[x] & can[y])
        printf("%d\n", d[y] - d[x]);
      else
        printf("1\n");
    }
  } else
    printf("No\n");
}
