//
// main.cpp
//

#include <algorithm>
#include <array>
#include <assert.h>
#include <complex>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <math.h>
#include <memory>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

using ll = int64_t;
using ull = uint64_t;
constexpr ll LL_MAX = numeric_limits<ll>::max();
constexpr ull ULL_MAX = numeric_limits<ull>::max();

template<typename T>
vector<T> make_vec_nd(T init, ll size) {
    return vector<T>(size, init);
}
template<typename T, typename... Args>
auto make_vec_nd(T init, ll size, Args... rest) {
    auto inner = make_vec_nd(init, rest...);
    return vector<decltype(inner)>(size, inner);
}

#define rep(i, a, b) for (ll i = (a); i < (b); i++)
#define rrep(i, a, b) for (ll i = (a)-1; i >= (b); i--)

struct Node {
	ll parent = -1;
	vector<ll> child;
	ll depth = 0;
};

void to_tree(vector<vector<ll>>& graph, vector<Node>& tree, vector<bool>& visited, ll node) {
	visited[node] = true;
	for (ll ch : graph[node]) {
		if (visited[ch]) {
			continue;
		}
		tree[ch].parent = node;
		tree[ch].depth = tree[node].depth + 1;
		tree[node].child.push_back(ch);
		to_tree(graph, tree, visited, ch);
	}
}

int main() {
	ll N;
	cin >> N;
	vector<vector<ll>> graph(N);
	rep(i,0,N-1) {
		ll a, b;
		cin >> a >> b;
		a--;
		b--;
		graph[a].push_back(b);
		graph[b].push_back(a);
	}
	vector<Node> tree(N);
	vector<bool> visited(N);
	to_tree(graph, tree, visited, 0);
	ll even_cnt = 0;
	rep(i,0,N) {
		if (tree[i].depth % 2 == 0) {
			even_cnt++;
		}
	}
	ll odd_cnt = N - even_cnt;
	vector<ll> ans(N);
	vector<ll> zeros;
	vector<ll> ones;
	vector<ll> twes;
	vector<ll> onetwoes;
	rep(i,1,N+1) {
		if (i % 3 == 0) {
			zeros.push_back(i);
		} else if (i % 3 == 1) {
			ones.push_back(i);
			onetwoes.push_back(i);
		} else if (i % 3 == 2) {
			twes.push_back(i);
			onetwoes.push_back(i);
		}
	}
	if (even_cnt <= N / 3) {
		rep(i,0,N) {
			if (tree[i].depth % 2 == 0) {
				ans[i] = zeros.back();
				zeros.pop_back();
			} else {
				if (!onetwoes.empty()) {
					ans[i] = onetwoes.back();
					onetwoes.pop_back();
				} else {
					ans[i] = zeros.back();
					zeros.pop_back();
				}
			}
		}
	} else if (odd_cnt <= N / 3) {
		rep(i,0,N) {
			if (tree[i].depth % 2 == 1) {
				ans[i] = zeros.back();
				zeros.pop_back();
			} else {
				if (!onetwoes.empty()) {
					ans[i] = onetwoes.back();
					onetwoes.pop_back();
				} else {
					ans[i] = zeros.back();
					zeros.pop_back();
				}
			}
		}
	} else {
		rep(i,0,N) {
			if (tree[i].depth % 2 == 0) {
				if (!ones.empty()) {
					ans[i] = ones.back();
					ones.pop_back();
				} else {
					ans[i] = zeros.back();
					zeros.pop_back();
				}
			} else {
				if (!twes.empty()) {
					ans[i] = twes.back();
					twes.pop_back();
				} else {
					ans[i] = zeros.back();
					zeros.pop_back();
				}
			}
		}
	}
	rep(i,0,N) {
		cout << ans[i];
		if (i != N-1) {
			cout << " ";
		}
	}
	cout << endl;
}
/*
 
 10
 1 2
 1 3
 1 4
 1 5
 1 6
 1 7
 1 8
 1 9
 1 10
 
 */


Measured memory_bytes: 36176