#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:64000000")
template <class T>
inline T sqr(T x) {
  return x * x;
}
int n, m, k;
vector<vector<int> > g;
char used[1 << 17];
int part[1 << 17];
int ans[1 << 17];
int size[2];
void dfs(int v, int color = 0) {
  ++size[color];
  part[v] = color;
  for (int i = 0; i < (int)((g[v]).size()); ++i) {
    int to = g[v][i];
    if (part[to] == -1) dfs(to, !color);
  }
}
void answer(int start) {
  int color = start;
  int cnt = 0;
  for (int p = 0; p < 2; ++p) {
    for (int i = 0; i < n; ++i) {
      if (part[i] != p || ans[i]) continue;
      ans[i] = color;
      if (++cnt == 3) ++color, cnt = 0;
    }
  }
  puts("YES");
  for (int i = 0; i < n; ++i) printf("%d ", ans[i]);
  exit(0);
}
bool check(int x, int y, int lim) {
  memset(used, 0, sizeof used);
  int cnt = 1;
  for (int i = 0; i < n; ++i) {
    if (part[i] != x || (int)((g[i]).size()) > size[y] - 2) continue;
    for (int j = 0; j < (int)((g[i]).size()); ++j) {
      int to = g[i][j];
      used[to] = true;
    }
    int v1 = -1, v2 = -1;
    for (int j = 0; j < n; ++j) {
      if (used[j] || part[j] == x) continue;
      if (v1 == -1)
        v1 = j;
      else
        v2 = j;
    }
    ans[i] = ans[v1] = ans[v2] = cnt;
    if (++cnt == lim) return true;
    memset(used, 0, sizeof used);
  }
  return false;
}
int main() {
  scanf("%d%d", &n, &m);
  g.resize(n);
  k = n / 3;
  for (int x, y; m--;) {
    scanf("%d%d", &x, &y);
    --x, --y;
    g[x].push_back(y);
    g[y].push_back(x);
  }
  memset(part, -1, sizeof part);
  for (int i = 0; i < n; ++i)
    if (part[i] == -1) dfs(i);
  if (size[0] % 3 == 0) answer(1);
  int x = 0, y = 1;
  if (size[x] % 3 == 2) swap(x, y);
  if (check(x, y, 2)) answer(2);
  if (check(y, x, 3)) answer(3);
  puts("NO");
  return 0;
}
