import std.algorithm;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;
import std.random;

static if (__VERSION__ >= 2075) {
  import std.datetime.stopwatch : StopWatch;
} else {
  import std.datetime : StopWatch;
}

final class Timer {
  immutable double timeout;
  StopWatch sw;
  this (double _timeout) {
    timeout = _timeout;
    sw.start ();
  }
  double elapsed () {
    static if (__VERSION__ >= 2075) {
      return sw.peek.total!"usecs" * 1e-6;
    } else {
      return sw.peek.usecs () * 1e-6;
    }
  }
  bool expired () {
    return elapsed () >= timeout;
  }
}

int n;
int[][] e;
int[] d;
int[] age;
int[] q;

final class Heap(T) {
  private:
    T [] a;
    int [] h;
    int [] g;
    int n;
    int size;
  pure nothrow @nogc
  void heapifyFront (int k) {
    immutable he = h[k];
    int i = k;
    int j = i << 1;
    while (j <= size) {
      if (j < size && a[h[j+1]] < a[h[j]]) {
        j++;
      }
      if (a[h[j]] >= a[he]) {
        break;
      }
      h[i] = h[j];
      g[h[i]] = i;
      i = j;
      j = i << 1;
    }
    if (i != k) {
      h[i] = he;
      g[he] = i;
    }
  }
  pure nothrow @nogc
  void heapifyBack (int k) {
    immutable he = h[k];
    int i = k;
    while (i > 1) {
      int j = i >> 1;
      if (a[he] >= a[h[j]]) {
        break;
      }
      h[i] = h[j];
      g[h[i]] = i;
      i = j;
    }
    if (i != k) {
      h[i] = he;
      g[he] = i;
    }
  }
  pure nothrow @nogc
  void insert (int i) {
    h[++size] = i;
    g[i] = size;
    heapifyBack (size);
  }
  public:
  pure nothrow @nogc
  void decreaseKey (int k, T value) in {
    assert (k >= 0 && k < n);
    assert (value < a[k]);
  } body {
    a[k] = value;
    immutable pos = g[k];
    if (!pos) {
      insert (k);
    } else {
      heapifyBack (pos);
    }
  }
  pure nothrow @nogc
  void update (int k, T value) in {
    assert (k >= 0 && k < n);
  } body {
    immutable pos = g[k];
    if (!pos) {
      a[k] = value;
      insert (k);
    } else if (value < a[k]) {
      a[k] = value;
      heapifyBack (pos);
    } else if (value > a[k]) {
      a[k] = value;
      heapifyFront (pos);
    }
  }
  pure nothrow @nogc
  int extractMin () {
    assert (size > 0);
    immutable he = h[1];
    g[he] = 0;
    if (--size) {
      h[1] = h[size+1];
      g[h[1]] = 1;
      heapifyFront (1);
    }
    return he;
  }
  pure nothrow @nogc
  inout(T) opIndex (size_t index) inout {
    return a[index];
  }

  @property pure nothrow @nogc
  bool empty () const { return size == 0; }

  this (int n_, T default_value = T.init) {
    n = n_;
    size = 0;
    a = uninitializedArray! (T[]) (n);
    a[] = default_value;
    h = new int[n+1];
    g = new int[n];
  }
}

int maxE (int[] a) {
  return reduce!((i, j) => max(i,j))(0, a);
}

int[] bfs (int s) {
  int left = 0, right = 1;
  q[0] = s;
  d[s] = 0;
  age[s] = s;
  int f = -1;
  while (left < right) {
    const int i = q[left++];
    const int nd = d[i];
    if (nd == 3) {
      if (f < 0) f = left;
    } else {
      foreach (j; e[i]) {
        if (age[j] != s) {
          age[j] = s;
          d[j] = nd + 1;
          q[right++] = j;
        }
      }
    }
  }
  if (f < 0) return [];
  return q[f .. right].dup;
}

void main() {
  
  readf (" %d", &n);
  e = new int[][n];
  foreach (k; 1 .. n) {
    int i, j;
    readf (" %d %d", &i, &j);
    e[--i] ~= --j;
    e[j] ~= i;
  }
  d = new int[n];
  //d[] = int.max;
  age = new int[n];
  age[] = -1;
  q = new int[n];
  rndGen.seed(123);

  auto e3 = new int[][n];
  foreach (i; 0 .. n) {
    e3[i] = bfs (i);
  }
  int[3] c;
  c[0] = c[1] = c[2] = n / 3;
  int o = 1;
  foreach (j; 0 .. n % 3) {
    ++c[o];
    if (++o == 3) o = 0;
  }

  auto res = new int[n];
  bool rec (int o, int v) {
    auto heap = new Heap!int (n, int.max);
    foreach (i; 0 ..n) heap.decreaseKey (i, e3[i].length.to!int);
    foreach (k; 0 .. v) {
      int i;
      while (true) {
        if (heap.empty) return false;
        i = heap.extractMin ();
        if (res[i] == 0) break;
      }
      res[i] = o + k * 3;
      foreach (j; e3[i]) if (res[j] == 0) {
        int w = heap[j];
        heap.decreaseKey (j, w - 1);
      }
    }
    return true;
  }

  if (!rec (1, c[1]) || !rec (2, c[2])) {
    writeln (-1);
    return;
  }
  int u = 3;
  foreach (i; 0 .. n) if (res[i] == 0) {
    res[i] = u;
    u += 3;
  }
  writefln ("%(%s %)", res);
}

