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

// int/long:		-2,147,483,648 - 2,147,483,647 (-2^31 <= int < 2^31)
// long/long long:	-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807 (-2^63 <= long < 2^63)

// lower_bound(A.begin(), A.end(), N)
// upper_bound(...

// A.erase(unique(A.begin(), A.end()), A.end())

// bit: &/and, |/or, ^/xor, ~/not

// getline(cin, String)
// while (getline(cin, S)) {}

// #include <cstdio>
// int a;
// scanf("%d", &a);
// printf("%d\n", a);
//
// for (int i=0; i<n; ++i)
// 	scanf("%d", &a[i]);
//
// char c;
// scanf(" %c", &c);
//
// cout << "\n";

// cout <<fixed <<setprecision(10)

// priority_queue<int> q;
// priority_queue<int, vector<int>, less<int>> q; // Default: vector, less
// priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> q;

// Graph
// Warshall-Floyd: Distance between each node, N^3
// Dijkstra: Distance from the start node, N^2
// DFS(Depth-First Search)

//
// Notes
//
// When specified less than N, try full scan.
// RE: empty vector
// Check Qs
// long/int
// xor -> count each bit
// Check values
// 	1,000,000 -> Loop
// 	100,000	-> vector(int:400KB, long:800KB) 

#define	INF (1<<30)
//1,073,741,824
//= 536,870,912 *2

#define	MOD 1000000007

#define	Rep0(i, n)	for (int i=0; i<n; i++)
#define	Rep1(i, n)	for (int i=1; i<=n; i++)
#define Sort(P)	sort(P.begin(), P.end())
#define Rev(P)	reverse(P.begin(), P.end())

int	main() {
	int	N;// Node# from 1 to N
	int	B;
	cin >> N;
	B=N-1;
	// Input, From/To(/Cost=1)
	vector<vector<int>>	bridge(B, vector<int> (2));
	for (int i=0; i<B; i++) {
		for (int j=0; j<2; j++) {
			cin >> bridge.at(i).at(j);
		}
	}
	// Struct for each node
	struct Node {
		vector<int> to_node;
		bool fix;
		int cost;
	};
	vector<Node> node(N+1);
	// Initialize (at(0) will not be used)
	for (int i=0; i<node.size(); i++) {
		node.at(i).fix=false;
		node.at(i).cost=INF;
	}
	// Data for each node
	for (int i=0; i<B; i++) {
		// From 1 to N
		int F=bridge.at(i).at(0);
		int T=bridge.at(i).at(1);
		node.at(F).to_node.push_back(T);
		node.at(T).to_node.push_back(F);
	}
	// Start
	// Start Node == Cost=0
	int StartNode=1;
	node.at(StartNode).cost=0;
	priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> q;
	q.push({node.at(StartNode).cost, StartNode});
	// For all reachable node from the start node (Unreachabel node not included)
	while (!q.empty()) {
		// Pickup the Node with minimum cost
		int c=q.top().at(0);
		int ii=q.top().at(1);
		q.pop();
		// If fixed, skip
		if(node.at(ii).fix)
			continue;
		// Change it to fixed and search for near-by nodes
		node.at(ii).fix=true;
		for (int i=0; i<node.at(ii).to_node.size(); i++) {
			int o_node=node.at(ii).to_node.at(i);
			// Update cost
			int o_cost=c+1;
			// Process only when smaller
			if (o_cost>=node.at(o_node).cost)
				continue;
			node.at(o_node).cost=o_cost;
			// Push into queue
			q.push({o_cost, o_node});
		}
	}
	vector<int> aa(N+1, 0);
	int n0=0;
	int n1=0;
	Rep1(i, N)
		if (0==node.at(i).cost%2)
			n0++;
		else
			n1++;
	int i1=1-3;
	int i2=2-3;
	int i3=3-3;
	if (n0<=N/3) {
		Rep1(i, N) {
			if (0==node.at(i).cost%2) {
				i3+=3;
				aa.at(i)=i3;
			} else {
				i1+=3;
				if (i1<=N)
					aa.at(i)=i1;
				else {
					i2+=3;
					if (i2<=N)
						aa.at(i)=i2;
					else {
						i3+=3;
						aa.at(i)=i3;
					}
				}
			}
		}
	} else if (n1<=N/3) {
		Rep1(i, N) {
			if (1==node.at(i).cost%2) {
				i3+=3;
				aa.at(i)=i3;
			} else {
				i1+=3;
				if (i1<=N)
					aa.at(i)=i1;
				else {
					i2+=3;
					if (i2<=N)
						aa.at(i)=i2;
					else {
						i3+=3;
						aa.at(i)=i3;
					}
				}
			}
		}
	} else {
		Rep1(i, N) {
			if (0==node.at(i).cost%2) {
				i1+=3;
				if (i1<=N)
					aa.at(i)=i1;
				else {
					i3+=3;
					if (i3<=N)
						aa.at(i)=i3;
					else {
						cout <<-1 <<endl;
						return 0;
					}
				}
			} else {
				i2+=3;
				if(i2<=N)
					aa.at(i)=i2;
				else {
					i3+=3;
					if (i3<=N)
						aa.at(i)=i3;
					else {
						cout <<-1 <<endl;
						return 0;
					}
				}
			}
		}
	}
	Rep1(i, N) {
		if (i<N)
			cout <<aa.at(i) <<' ';
		else
			cout <<aa.at(i) <<endl;
	}
	return 0;
}



Measured memory_bytes: 35940