#include <bits/stdc++.h>
const int maxn = 100005;
int nbs[maxn], ev[maxn * 2], next[maxn * 2], color[maxn], d[maxn], ans[maxn],
    size[2], view[maxn], n, m, k;
void addedge(int x, int y) {
  next[++k] = nbs[x];
  ev[k] = y;
  nbs[x] = k;
}
void init() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < m; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    addedge(x, y);
    addedge(y, x);
    ++d[x];
    ++d[y];
  }
}
void dfs(int x, int col) {
  color[x] = col;
  ++size[col];
  for (int i = nbs[x]; i; i = next[i]) {
    if (color[ev[i]] == -1) dfs(ev[i], col ^ 1);
  }
}
void output(int x) {
  int y = 0;
  for (int i = 1; i <= n; ++i) {
    if (!ans[i] && color[i] == 0) {
      ans[i] = x;
      ++y;
      if (y % 3 == 0) ++x;
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (!ans[i] && color[i] == 1) {
      ans[i] = x;
      ++y;
      if (y % 3 == 0) ++x;
    }
  }
  printf("YES\n");
  for (int i = 1; i <= n; ++i) printf("%d ", ans[i]);
  printf("\n");
}
void solve(int x, int y = 1) {
  memset(view, 0, sizeof(view));
  ans[x] = y;
  for (int i = nbs[x]; i; i = next[i]) view[ev[i]] = 1;
  int k = 0;
  for (int i = 1; i <= n && k < 2; ++i) {
    if (!ans[i] && color[i] != color[x] && !view[i]) {
      ans[i] = y;
      ++k;
    }
  }
}
void work() {
  memset(color, -1, sizeof(color));
  for (int i = 1; i <= n; ++i) {
    if (color[i] == -1) dfs(i, 0);
  }
  if (size[0] % 3 == 0)
    output(1);
  else {
    int col = size[0] % 3 - 1, find = 0;
    for (int i = 1; i <= n && !find; ++i) {
      if (color[i] == col && d[i] + 2 <= size[col ^ 1]) {
        solve(i);
        find = 1;
      }
    }
    if (find)
      output(find + 1);
    else {
      col ^= 1;
      int t = 0;
      for (int i = 1; i <= n && find < 2; ++i) {
        if (color[i] == col && d[i] + 2 <= size[col ^ 1]) {
          solve(i, find + 1);
          ++find;
        }
      }
      if (find == 2)
        output(find + 1);
      else
        printf("NO\n");
    }
  }
}
int main() {
  init();
  work();
  return 0;
}
