//Author:- S_Aditya

#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//using namespace __gnu_pbds;
using namespace std;
//typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
#define ll long long 
#define scn(n) scanf("%d",&n)
#define lscn(n) scanf("%lld",&n)
#define lpri(n) printf("%lld",n)
#define pri(n) printf("%d",n)
#define priln(n) printf("%d\n",n)
#define lpriln(n) printf("%lld\n",n)
#define rep(i,init,n) for(int i=init;i<n;i++)
#define pb push_back     
#define mp make_pair
#define F first
#define S second
#define gcd __gcd
#define inf INT_MAX
#define ninf INT_MIN
const ll mod=1e9+7;         
const int N=2e5+4;

vector<int> v[N];

int colour[N],white,black,minority,minority_colour; //0->white 1->black

int final[N];

void dfs_colour(int node,int par,int col)
{
    colour[node]=col;
    
    if(col==0)
    white++;
    else
    black++;
    
    for(int it:v[node])
    if(it!=par)
    dfs_colour(it,node,col^1);
}

int zero,one,two; //zero represents count of numbers left with remainder 0 with 3
//definition of one and two is similar

int main()                  
{
    int n;
    
    scn(n);
    
    rep(i,0,n-1)
    {
        int a,b;
        
        scn(a); scn(b);
        
        v[a].pb(b);
        
        v[b].pb(a);
    }
    
    memset(final,-1,sizeof(final));
    
    zero=one=two=(n/3);
    
    if(n%3==1)
    one++;
    else if(n%3==2)
    one++,two++;
    
    //bipartite colouring is useful because all pairs of nodes with distance 3 will have
    //alternate colour(a key observation)
    dfs_colour(1,-1,0);
    
    if(white<black)
    minority=white,minority_colour=0;
    else
    minority=black,minority_colour=1;
    
    if(minority<=zero) //can we label all nodes in samller group with a multiple of 3?
    {
        //if we can do so, let's do it! (all distance 3 pairs label product will be a multiple of 3)
        
        //paint the samller group
        rep(i,1,n+1)
        if(colour[i]==minority_colour)
        final[i]=0,zero--;
        
        //paint the larger group
        rep(i,1,n+1)
        if(final[i]==-1)
        {
            if(zero)
            final[i]=0,zero--;
            else if(one)
            final[i]=1,one--;
            else
            final[i]=2,two--;
        }
    }
    else
    {
        //then we have to distribute 1's in smaller group and two's in larger group
        //or vice versa to ensure opposite colour nodes do not have same remainder with
        //three(i.e 1,1 or 2,2)
        
        //paint the smaller group
        rep(i,1,n+1)
        if(colour[i]==minority_colour)
        {
            if(one)
            final[i]=1,one--;
            else
            final[i]=0,zero--;
        }
        
        //paint the larger group
        rep(i,1,n+1)
        if(final[i]==-1)
        {
            if(zero)
            final[i]=0,zero--;
            else
            final[i]=2,two--;
        }
    }
    
    int add[3]={0};
    
    add[0]=3;
    
    int ans[n+1];
    
    rep(i,1,n+1)
    {
        ans[i]=final[i]+add[final[i]];
        
        add[final[i]]+=3;
    }
    
    rep(i,1,n+1)
    printf("%d ",ans[i]);
} 



Measured memory_bytes: 19200