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 Rust (1.15.1) (judge verdict: Accepted)

#![allow(unused_imports)]
#![allow(non_snake_case)]
use std::cmp::*;
use std::collections::*;
use std::io::Write;

#[allow(unused_macros)]
macro_rules! debug {
    ($($e:expr),*) => {
        #[cfg(debug_assertions)]
        $({
            let (e, mut err) = (stringify!($e), std::io::stderr());
            writeln!(err, "{} = {:?}", e, $e).unwrap()
        })*
    };
}

fn dfs(
    cur: usize,
    parent: usize,
    graph: &Vec<Vec<usize>>,
    color: &mut Vec<i32>,
    parents: &mut Vec<Option<usize>>,
) {
    for &to in graph[cur].iter() {
        if to == parent {
            continue;
        }
        color[to] = -1 * color[cur];
        parents[to] = Some(cur);
        dfs(to, cur, graph, color, parents);
    }
}

fn main() {
    let n = read::<usize>();
    let mut graph = vec![vec![]; n];
    for i in 0..n - 1 {
        let v = read_vec::<usize>();
        let (a, b) = (v[0] - 1, v[1] - 1);
        graph[a].push(b);
        graph[b].push(a);
    }
    let mut color = vec![0; n];
    color[0] = 1;
    let mut parents = vec![vec![None; n]; 3];
    dfs(0, 0, &graph, &mut color, &mut parents[0]);
    let ones = color.iter().filter(|&&x| x == 1).count();
    let minus = n - ones;

    let mut residuals = vec![vec![]; 3];
    for i in 1..n + 1 {
        residuals[i % 3].push(i);
    }

    let mut assign = vec![0; n];
    if ones <= n / 3 || minus <= n / 3 {
        let three_color = if ones <= n / 3 { 1 } else { -1 };

        let mut pointer = [0; 3];
        for i in 0..n {
            if color[i] == three_color {
                assign[i] = residuals[0][pointer[0]];
                pointer[0] += 1;
            }
        }
        for i in 0..n {
            if color[i] != three_color {
                'inner: for pi in 0..3 {
                    if pointer[pi] < residuals[pi].len() {
                        assign[i] = residuals[pi][pointer[pi]];
                        pointer[pi] += 1;
                        break 'inner;
                    }
                }
                assert!(assign[i] != 0);
            }
        }
    } else {
        let mut pointer = [0; 3];
        for i in 0..n {
            let ci = if color[i] == 1 { 1 } else { 2 };
            if pointer[ci] < residuals[ci].len() {
                assign[i] = residuals[ci][pointer[ci]];
                pointer[ci] += 1;
            } else {
                assign[i] = residuals[0][pointer[0]];
                pointer[0] += 1;
            }
        }
    }
    for ans in assign {
        print!("{} ", ans);
    }
    println!("");
}

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>()
        .split_whitespace()
        .map(|e| e.parse().ok().unwrap())
        .collect()
}