#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
vector<int> det[2];
vector<int> e[100007];
vector<int> col, bel, ans;
void bfs(int u) {
  queue<int> Q;
  Q.push(u);
  while (Q.size()) {
    int now = Q.front();
    Q.pop();
    det[col[now]].push_back(now);
    for (typeof(e[now].begin()) it = e[now].begin(); it != e[now].end(); it++) {
      assert(col[now] != col[*it]);
      if (1 - col[now] == col[*it]) continue;
      assert(col[*it] == -1);
      col[*it] = 1 - col[now];
      Q.push(*it);
    }
  }
}
void color(int idx) {
  int cnt = 3;
  for (typeof(det[0].begin()) it = det[0].begin(); it != det[0].end(); it++) {
    if (ans[*it] != -1) continue;
    if (!cnt) ++idx, cnt = 3;
    ans[*it] = idx;
    --cnt;
  }
  assert(!cnt || 3 == cnt);
  for (typeof(det[1].begin()) it = det[1].begin(); it != det[1].end(); it++) {
    if (ans[*it] != -1) continue;
    if (!cnt) ++idx, cnt = 3;
    ans[*it] = idx;
    --cnt;
  }
}
int main() {
  int n, m, k;
  ios::sync_with_stdio(false);
  cin >> n >> m;
  k = n / 3;
  for (int i = 0; i < m; i++) {
    int x, y;
    cin >> x >> y;
    --x, --y;
    e[x].push_back(y);
    e[y].push_back(x);
  }
  col.resize(n);
  fill(col.begin(), col.end(), -1);
  vector<int> lr[3];
  for (int i = 0; i < n; i++)
    if (-1 == col[i]) {
      col[i] = 0;
      bfs(i);
    }
  bool noans = false;
  ans.resize(n);
  fill(ans.begin(), ans.end(), -1);
  if (det[0].size() % 3 == 0)
    color(1);
  else {
    int left = 0;
    if (det[1].size() % 3 == 1) left = 1;
    bool ok = false;
    for (typeof(det[left].begin()) it = det[left].begin();
         it != det[left].end(); it++)
      if ((int)e[*it].size() <= (int)det[1 - left].size() - 2) {
        ok = true;
        vector<bool> cant;
        cant.resize(n);
        fill(cant.begin(), cant.end(), false);
        for (typeof(e[*it].begin()) it1 = e[*it].begin(); it1 != e[*it].end();
             it1++)
          cant[*it1] = true;
        int colored = 0;
        for (typeof(det[1 - left].begin()) it1 = det[1 - left].begin();
             it1 != det[1 - left].end(); it1++) {
          if (colored == 2) break;
          if (!cant[*it1]) {
            ans[*it1] = 1;
            ++colored;
          }
        }
        ans[*it] = 1;
        break;
      }
    if (ok) {
      color(2);
      goto there;
    }
    int t1 = -1, t2 = -1;
    int right = 1 - left;
    for (typeof(det[right].begin()) it = det[right].begin();
         it != det[right].end(); it++) {
      if ((int)e[*it].size() <= (int)det[left].size() - 2) {
        if (t1 == -1) {
          t1 = *it;
          continue;
        }
        t2 = *it;
        break;
      }
    }
    if (t2 == -1) {
      noans = true;
      goto there;
    }
    vector<bool> cant;
    cant.resize(n);
    fill(cant.begin(), cant.end(), false);
    for (typeof(e[t1].begin()) it1 = e[t1].begin(); it1 != e[t1].end(); it1++)
      cant[*it1] = true;
    int colored = 0;
    ans[t1] = 1;
    for (typeof(det[left].begin()) it1 = det[left].begin();
         it1 != det[left].end(); it1++) {
      if (colored == 2) break;
      if (!cant[*it1]) {
        ans[*it1] = 1;
        ++colored;
      }
    }
    fill(cant.begin(), cant.end(), false);
    for (typeof(e[t2].begin()) it1 = e[t2].begin(); it1 != e[t2].end(); it1++)
      cant[*it1] = true;
    colored = 0;
    ans[t2] = 2;
    for (typeof(det[left].begin()) it1 = det[left].begin();
         it1 != det[left].end(); it1++) {
      if (colored == 2) break;
      if (!cant[*it1]) {
        ans[*it1] = 2;
        ++colored;
      }
    }
    color(3);
  }
there:
  if (noans) {
    cout << "NO\n";
    return 0;
  }
  cout << "YES\n";
  for (int i = 0; i < n; i++) {
    if (i) cout << " ";
    cout << ans[i];
  }
  cout << endl;
  return 0;
}
