#include <bits/stdc++.h>
using namespace std;

#define int long long
#define REP(i, n) for ( int i = 0; i < (n); i++ )

vector<int> G[200001];
int N;

template< typename T >
struct edge {
  int src, to;  
  T cost;

  edge(int to, T cost) : src(-1), to(to), cost(cost) {}

  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

  edge &operator=(const int &x) {
    to = x;
    return *this;
  }

  operator int() const { return to; }
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedGraph = vector< Edges< T > >;
using UnWeightedGraph = vector< vector< int > >;
template< typename T >
using Matrix = vector< vector< T > >;

template< typename T >
pair< T, int > dfs(const WeightedGraph< T > &g, int idx, int par) {
  pair< T, int > ret(0, idx);
  for(auto &e : g[idx]) {
    if(e.to == par) continue;
    auto cost = dfs(g, e.to, idx);
    cost.first += e.cost;
    ret = max(ret, cost);
  }
  return ret;
}

template< typename T >
T tree_diameter(const WeightedGraph< T > &g) {
  auto p = dfs(g, 0, -1);
  auto q = dfs(g, p.second, -1);
  return (q.first);
}

signed main() {
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  cin >> N;
  WeightedGraph<int> wg(N);  
  for ( int i = 0; i < N-1; i++ ) {
    int a, b;
    cin >> a >> b;
    a--; b--;
    G[a].push_back(b);
    G[b].push_back(a);
    wg[a].push_back(edge<int>(b, 1));    
    wg[b].push_back(edge<int>(a, 1));    
  }

  if ( tree_diameter(wg) <= 2 ) {
    for ( int i = 0; i < N; i++ ) {
      if ( i ) cout << " ";
      cout << i+1;
    }
    cout << endl;
    return 0;
  }

  int cnt = 0;
  while ( cnt < 1 ) {
    int H = 0, B = 0;
    vector<int> col(N, -1);    
    {
      queue<int> Q;
      Q.push(cnt);
      col[cnt] = 0; 
      while ( !Q.empty() ) {
	int v = Q.front(); Q.pop();
	for ( int u: G[v] ) {
	  if ( col[u] != -1 ) continue;
	  col[u] = 1-col[v];
	  Q.push(u);	
	}
      }    
    }

    for ( int i = 0; i < N; i++ ) {
      if ( col[i] == 0 ) H++;
      else B++;
    }
    
    // for ( int i: col ) cout << i << endl;
    queue<int> m[3], m12;
    for ( int i = 1; i <= N; i++ ) {
      m[i%3].push(i);
      if ( i%3 ) m12.push(i);      
    }

    vector<int> ans(N);
    if ( H <= m[0].size() ) {
      for ( int i = 0; i < N; i++ ) {
	if ( col[i] == 0 ) {
	  ans[i] = m[0].front();
	  m[0].pop();
	} else {
	  if ( m12.size() ) {
	    ans[i] = m12.front();
	    m12.pop();
	  } else {
	    ans[i] = m[0].front();
	    m[0].pop();
	  }
	}
      }
      for ( int i = 0; i < N; i++ ) {
	if ( i ) cout << " ";
	cout << ans[i];
      }
      cout << endl;
      return 0;
    }

    if ( B <= m[0].size() ) {
      for ( int i = 0; i < N; i++ ) {
	if ( col[i] == 1 ) {
	  ans[i] = m[0].front();
	  m[0].pop();
	} else {
	  if ( m12.size() ) {
	    ans[i] = m12.front();
	    m12.pop();
	  } else {
	    ans[i] = m[0].front();
	    m[0].pop();
	  }
	}
      }
      for ( int i = 0; i < N; i++ ) {
	if ( i ) cout << " ";
	cout << ans[i];
      }
      cout << endl;
      return 0;
    }
        
    bool flag = true;
    for ( int i = 0; i < N; i++ ) {
      if ( col[i] == 0 ) {
	if ( m[1].size() ) {
	  ans[i] = m[1].front();
	  m[1].pop();	
	} else {
	  if ( m[0].size() == 0 ) {
	    flag = false;
	    break;	  
	  }
	  ans[i] = m[0].front();
	  m[0].pop();	
	}
      } else {
	if ( m[2].size() ) {
	  ans[i] = m[2].front();
	  m[2].pop();	
	} else {
	  if ( m[0].size() == 0 ) {
	    flag = false;
	    break;	  
	  }
	  ans[i] = m[0].front();
	  m[0].pop();	
	}
      }
    }

    if ( flag ) {
      for ( int i = 0; i < N; i++ ) {
	if ( i ) cout << " ";
	cout << ans[i];
      }
      cout << endl;
      return 0;
    }

    cnt++;
  }

  assert(0);  
  cout << -1 << endl;

  return 0;
}


Measured memory_bytes: 40320