#include <bits/stdc++.h>
using namespace std;
int cmp[100010];
int sz[3];
vector<int> E[100010];
int asst[100010];
void assign_all(int N) {
  assert(sz[1] % 3 == 0);
  assert(sz[2] % 3 == 0);
  int k = 1;
  int left = 3;
  for (int j = 1; j <= N; j++) {
    if (cmp[j] != 1) continue;
    asst[j] = k;
    left--;
    if (left == 0) {
      k++;
      left = 3;
    }
  }
  assert(left == 3);
  for (int j = 1; j <= N; j++) {
    if (cmp[j] != 2) continue;
    asst[j] = k;
    left--;
    if (left == 0) {
      k++;
      left = 3;
    }
  }
}
bool good[100010];
void print_all(int N) {
  for (int i = (1); i <= (N); i++) {
    if (i > 1) cout << " ";
    cout << asst[i];
  }
}
void join(int a, int b, int c, int k) {
  assert(a > 0 && b > 0 && c > 0);
  asst[a] = asst[b] = asst[c] = k;
  cmp[a] = cmp[b] = cmp[c] = 0;
}
int main() {
  int N, M;
  cin >> N >> M;
  for (int j = 0; j < M; j++) {
    int a, b;
    cin >> a >> b;
    E[a].push_back(b);
    E[b].push_back(a);
  }
  for (int i = (1); i <= (N); i++) {
    if (cmp[i] == 0) {
      cmp[i] = 1;
      queue<int> Q;
      Q.push(i);
      while (!Q.empty()) {
        int s = Q.front();
        Q.pop();
        int numE = E[s].size();
        for (int x = 0; x < numE; x++) {
          int j = E[s][x];
          if (cmp[j] != 0) continue;
          cmp[j] = 1 + (2 - cmp[s]);
          Q.push(j);
        }
      }
    }
  }
  for (int i = (1); i <= (N); i++) sz[cmp[i]]++;
  if (sz[1] % 3 == 0) {
    cout << "YES" << endl;
    assign_all(N);
    print_all(N);
    return 0;
  } else {
    if (sz[1] % 3 == 2) {
      swap(sz[1], sz[2]);
      for (int i = (1); i <= (N); i++) cmp[i] = 3 - cmp[i];
    }
    for (int i = (1); i <= (N); i++) {
      if (cmp[i] == 2) continue;
      if (E[i].size() <= (sz[2] - 2)) {
        cout << "YES" << endl;
        memset(good, true, sizeof(good));
        int numE = E[i].size();
        for (int x = 0; x < numE; x++) good[E[i][x]] = false;
        int a = -1;
        int b = -1;
        for (int j = (1); j <= (N); j++) {
          if (good[j] && (cmp[j] != cmp[i])) {
            b = a;
            a = j;
          }
        }
        join(i, a, b, (N + 2) / 3);
        sz[1]--;
        sz[2] -= 2;
        assign_all(N);
        print_all(N);
        return 0;
      }
    }
    int num_found = 0;
    for (int s = 0; s < 2; s++) {
      for (int i = (1); i <= (N); i++) {
        if (cmp[i] != 2) continue;
        if (E[i].size() >= (sz[1] - 1)) continue;
        memset(good, true, sizeof(good));
        int numE = E[i].size();
        for (int x = 0; x < numE; x++) good[E[i][x]] = false;
        int a = -1;
        int b = -1;
        for (int j = (1); j <= (N); j++) {
          if (good[j] && (cmp[j] == 1)) {
            b = a;
            a = j;
          }
        }
        join(i, a, b, (N + 2 - 3 * s) / 3);
        num_found++;
        break;
      }
    }
    sz[1] -= 4;
    sz[2] -= 2;
    if (num_found < 2) {
      cout << "NO" << endl;
      return 0;
    } else {
      cout << "YES" << endl;
      assign_all(N);
      print_all(N);
      return 0;
    }
  }
  cout << "NO" << endl;
}
