Problem:
Score : 600 points

Problem Statement

We have a tree with N vertices. The vertices are numbered 1 to N, and the i-th edge connects Vertex a_i and Vertex b_i.

Takahashi loves the number 3. He is seeking a permutation p_1, p_2, \ldots , p_N of integers from 1 to N satisfying the following condition:

For every pair of vertices (i, j), if the distance between Vertex i and Vertex j is 3, the sum or product of p_i and p_j is a multiple of 3.

Here the distance between Vertex i and Vertex j is the number of edges contained in the shortest path from Vertex i to Vertex j.

Help Takahashi by finding a permutation that satisfies the condition.

Constraints

2\leq N\leq 2\times 10^5

1\leq a_i, b_i \leq N

The given graph is a tree.

Input

Input is given from Standard Input in the following format:

N
a_1 b_1
a_2 b_2
\vdots
a_{N-1} b_{N-1}

Output

If no permutation satisfies the condition, print -1.

Otherwise, print a permutation satisfying the condition, with space in between.
If there are multiple solutions, you can print any of them.

Sample Input 1

5
1 2
1 3
3 4
3 5

Sample Output 1

1 2 5 4 3

The distance between two vertices is 3 for the two pairs (2, 4) and (2, 5).

p_2 + p_4 = 6

p_2\times p_5 = 6

Thus, this permutation satisfies the condition.

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Runtime Error)

import java.util.*;
import java.io.*;
 
public class Main {
    static ArrayList<ArrayList<Integer>> map;
    static long[] dist;
    public static void main(String[] args) throws Exception {
        FastScanner sc = new FastScanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        int n = sc.nextInt();
        dist = new long[n];
        Arrays.fill(dist,Long.MAX_VALUE);
        dist[0] = 0;
        boolean[] arr = new boolean[n];
        arr[0] = true;
        map = new ArrayList<ArrayList<Integer>>();
        for(int i = 0; i < n; i++){
            map.add(new ArrayList<Integer>());
        }
        for(int i = 0; i < n-1; i++){
            int a = sc.nextInt()-1;
            int b = sc.nextInt()-1;
            map.get(a).add(b);
            map.get(b).add(a);
        }
        dfs(0,0,arr);
        ArrayList<Integer> red = new ArrayList<Integer>();
        ArrayList<Integer> blue = new ArrayList<Integer>();
        for(int i = 1; i < n; i++){
            if(dist[i] % 2 == 0){
                red.add(i);
            }else{
                blue.add(i);
            }
        }
        int n3 = n/3;
        int[] ans = new int[n];
        StringBuilder sb = new StringBuilder();
        if(red.size() >= n3 && blue.size() >= n3){
            int j = 0;
            for(int i = 1; i <= n; i+=3){
                ans[red.get(j)] = i;
                j++;
                if(j >= red.size()){
                    break;
                }
            }
            j = 0;
            for(int i = 2; i <= n; i+=3){
                ans[blue.get(j)] = i;
                j++;
                if(j >= blue.size()){
                    break;
                }
            }
            int pow3 = 3;
            for(int a : ans){
                if(a == 0){
                    a = pow3;
                    pow3 += 3;
                }
                sb.append(a + " ");
            }
        }else if(red.size() < n3){
            int j = 0;
            for(int i = 3; i <= n; i+=3){
                if(j >= red.size()){
                    break;
                }
                ans[red.get(j)] = i;
                j++;
            }
            int k = 0;
            for(int i = 1; i <= n; i++){
                if(i % 3 == 0 && j*3 > i){
                    continue;
                }
                ans[blue.get(k)] = i;
                k++;
            }
            for(int a : ans){
                sb.append(a + " ");
            }
        }else if(blue.size() < n3){
            int j = 0;
            for(int i = 3; i <= n; i+=3){
                if(j >= blue.size()){
                    break;
                }
                ans[red.get(j)] = i;
                j++;
            }
            int k = 0;
            for(int i = 1; i <= n; i++){
                if(i % 3 == 0 && j*3 > i){
                    continue;
                }
                ans[red.get(k)] = i;
                k++;
            }
            for(int a : ans){
                sb.append(a + " ");
            }
        }
        pw.println(sb.toString().trim());
        pw.flush();
    }
    
    public static void dfs(int s, long dd, boolean[] a){
        for(int b : map.get(s)){
            if(!a[b]){
                dist[b] = dd+1;
                a[b] = true;
                dfs(b,dd+1,a);
                a[b] = false;
            }
        }
        return;
    }
    
}

class Point{
    int x;
    long d;
    public Point(int x, long d){
        this.x = x;
        this.d = d;
    }
}

class FastScanner {
    private BufferedReader reader = null;
    private StringTokenizer tokenizer = null;
    public FastScanner(InputStream in) {
        reader = new BufferedReader(new InputStreamReader(in));
        tokenizer = null;
    }

    public String next() {
        if (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public String nextLine() {
        if (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                return reader.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken("\n");
    }

    public long nextLong() {
        return Long.parseLong(next());
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    public double nextDouble() {
         return Double.parseDouble(next());
    }

    public int[] nextIntArray(int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; i++)
            a[i] = nextInt();
        return a;
    }

    public long[] nextLongArray(int n) {
        long[] a = new long[n];
        for (int i = 0; i < n; i++)
            a[i] = nextLong();
        return a;
    } 
}