#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:10000000000")
using namespace std;
const int MOD = 1000000007;
const int INF = 1000000007LL;
const long long INF2 = 1000000007LL * 1000000007LL;
const long double EPS = 1e-9;
const int SIZE = 100100;
mt19937 rng(time(0));
uniform_int_distribution<int> uid(-1000000000, 1000000000);
int n, m, k;
vector<int> g[SIZE], r[2], gn[SIZE];
int u[SIZE];
int u1[SIZE];
int a, b;
void dfs(int v, int c = 1) {
  if (u1[v]) return;
  u1[v] = c;
  r[c - 1].push_back(v);
  for (auto& i : g[v]) dfs(i, 3 - c);
}
bool cmp(int x, int y) { return g[x].size() < g[y].size(); }
vector<int> opposite(int x) {
  set<int> st;
  for (int i = 0; i < n; ++i) st.insert(i);
  for (auto& i : g[x]) st.erase(i);
  vector<int> rs;
  for (auto& i : st) {
    if (u1[i] == u1[x]) continue;
    rs.push_back(i);
    if (rs.size() == 2) break;
  }
  return rs;
}
bool cmp2(int x, int y) { return gn[x].size() > gn[y].size(); }
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  k = n - 1;
  for (int rep_iter = 0; rep_iter < m; ++rep_iter) {
    cin >> a >> b;
    --a;
    --b;
    g[a].push_back(b);
    g[b].push_back(a);
  }
  for (int i = 0; i < n; ++i) {
    sort(begin(g[i]), end(g[i]));
  }
  for (int i = 0; i < n; ++i) {
    dfs(i);
  }
  if (r[0].size() % 3 == 0) {
    for (auto& i : r[0]) {
      u[i] = k / 3 + 1;
      --k;
    }
    for (auto& i : r[1]) {
      u[i] = k / 3 + 1;
      --k;
    }
    cout << "YES\n";
    for (int i = 0; i < n; ++i) {
      cout << u[i] << ' ';
    }
    return 0;
  }
  if (r[1].size() % 3 == 1) swap(r[0], r[1]);
  sort(begin(r[0]), end(r[0]), cmp);
  if (g[r[0][0]].size() <= r[1].size() - 2) {
    vector<int> x = opposite(r[0][0]);
    u[r[0][0]] = k / 3 + 1;
    for (auto& i : x) u[i] = k / 3 + 1;
    x.push_back(r[0][0]);
    k -= 3;
    for (auto& i : r[0]) {
      if ((find(begin(x), end(x), i) != end(x))) continue;
      u[i] = k / 3 + 1;
      --k;
    }
    for (auto& i : r[1]) {
      if ((find(begin(x), end(x), i) != end(x))) continue;
      u[i] = k / 3 + 1;
      --k;
    }
    cout << "YES\n";
    for (int i = 0; i < n; ++i) {
      cout << u[i] << ' ';
    }
    return 0;
  }
  for (auto& i : r[0]) {
    if (g[i].size() == r[1].size()) break;
    gn[opposite(i)[0]].push_back(i);
  }
  sort(begin(r[1]), end(r[1]), cmp2);
  if (gn[r[1][1]].size() < 2) {
    cout << "NO";
    return 0;
  }
  vector<int> x;
  x.push_back(r[1][0]);
  x.push_back(gn[r[1][0]][0]);
  x.push_back(gn[r[1][0]][1]);
  x.push_back(r[1][1]);
  x.push_back(gn[r[1][1]][0]);
  x.push_back(gn[r[1][1]][1]);
  for (auto& i : x) {
    u[i] = k / 3 + 1;
    --k;
  }
  for (auto& i : r[0]) {
    if ((find(begin(x), end(x), i) != end(x))) continue;
    u[i] = k / 3 + 1;
    --k;
  }
  for (auto& i : r[1]) {
    if ((find(begin(x), end(x), i) != end(x))) continue;
    u[i] = k / 3 + 1;
    --k;
  }
  cout << "YES\n";
  for (int i = 0; i < n; ++i) {
    cout << u[i] << ' ';
  }
  return 0;
}
