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 C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Linq;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args) {
#if DEBUG
        MyDebugger.Test(process, "../TextFile1.txt");
        //MyDebugger.Test(process, "../TextFile2.txt");
        //MyDebugger.MakeTestCase("../TextFile2.txt");
#else
        object ret = process(new StreamReader(Console.OpenStandardInput()));
        Console.WriteLine(ret);
#endif
    }

    static object process(TextReader input) {
        var n = int.Parse(input.ReadLine());

        var points = new List<int>[n];
        var numset = new HashSet<int>();
        var per0 = new Queue<int>();
        var per1 = new Queue<int>();
        var per2 = new Queue<int>();
        var perX = new Queue<int>();

        for (int i = 0; i < n; i++) {
            points[i] = new List<int>();
            numset.Add(i + 1);

            var per = (i + 1) % 3;
            if      (per == 0) per0.Enqueue(i + 1);
            else if (per == 1) per1.Enqueue(i + 1);
            else if (per == 2) per2.Enqueue(i + 1);
            else               perX.Enqueue(i + 1);
        }
        for (int i = 0; i < n - 1; i++) {
            var spl = input.ReadLine().Split(' ');
            var a = int.Parse(spl[0]) - 1;
            var b = int.Parse(spl[1]) - 1;

            points[a].Add(b);
            points[b].Add(a);
        }

        //各頂点から3で行ける頂点の集合
        var tbl = new HashSet<int>[n];

        for (int i = 0; i < n; i++) {
            var x = new HashSet<int>();
            Find(points, i, -1, 3, x);
            tbl[i] = x;
        }

        //
        var ret = new int[n];

        Func<int, int, bool> Select = (x, y) => {
            var xi = ret[x];
            var yi = ret[y];

            if (xi == 0 && yi == 0) {
                if (per0.Any()) {
                    ret[x] = per0.Dequeue();
                } else if (per1.Any() && per2.Any()) {
                    ret[x] = per1.Dequeue();
                    ret[y] = per2.Dequeue();
                } else {
                    return false;
                }
                return true;
            }

            if(xi != 0 && xi % 3 == 0){
                return true;
            }

            if(yi != 0 && yi % 3 == 0) {
                return true;
            }

            if (xi != 0 && yi == 0) {
                if (xi % 3 == 1 && per2.Any()) {
                    ret[y] = per2.Dequeue();
                }else if(xi % 3 == 2 && per1.Any()) {
                    ret[y] = per1.Dequeue();
                } else if(per0.Any()){
                    ret[y] = per0.Dequeue();
                } else {
                    return false;
                }
                return true;
            }
            
            if (xi == 0 && yi != 0) {
                if (yi % 3 == 1 && per2.Any()) {
                    ret[x] = per2.Dequeue();
                }else if(yi % 3 == 2 && per1.Any()) {
                    ret[x] = per1.Dequeue();
                } else if(per0.Any()){
                    ret[x] = per0.Dequeue();
                } else {
                    return false;
                }
                return true;
            }

            return (xi + yi) % 3 == 0;
        };
                     
        for(int i=0; i<n; i++) {
            foreach(var to in tbl[i]) {
                var ok = Select(i, to);
                if (!ok) {
                    return -1;
                }
            }
        }

        Func<int> Any = () => {
            if (per0.Any()) return per0.Dequeue();
            if (per1.Any()) return per1.Dequeue();
            if (per2.Any()) return per2.Dequeue();
            if (perX.Any()) return perX.Dequeue();
            return -1;
        };

        var sb = new StringBuilder();
        foreach(var x in ret) {
            if (x == 0) sb.Append(Any().ToString());
            else sb.Append(x.ToString());
            sb.Append(' ');
        }

        return sb;
    }

    //static bool IsOk(int x, int y) {
    //    if ((x + y) % 3 == 0) return true;
    //    if (x % 3 == 0) return true;
    //    if (y % 3 == 0) return true;
    //    return false;
    //}

    static void Find(List<int>[] points, int p, int from, int power, HashSet<int> box) {
        if (power == 1) {
            foreach (var to in points[p]) {
                if (to != from) box.Add(to);
            }
        } else {
            foreach (var to in points[p]) {
                if (to != from) {
                    Find(points, to, p, power - 1, box);
                }
            }
        }
    }
}