use std::collections::{HashMap, HashSet};
use std::io::Write;
use std::ops::Add;

#[allow(unused)]
macro_rules! debug {
    ($($format:tt)*) => (write!(std::io::stderr(), $($format)*).unwrap());
}
#[allow(unused)]
macro_rules! debugln {
    ($($format:tt)*) => (writeln!(std::io::stderr(), $($format)*).unwrap());
}

type Graph = Vec<Vec<OneBased>>;

fn main() {
    let n: usize = {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).unwrap();
        let s = s.trim_right().to_owned();
        s.parse().unwrap()
    };

    let mut v: Vec<(usize, usize)> = Vec::new();
    for _ in 0..(n - 1) {
        let v_i = {
            let mut s = String::new();
            std::io::stdin().read_line(&mut s).unwrap();
            let s = s.trim_right().to_owned();
            let mut ws = s.split_whitespace();
            let a = ws.next().unwrap().parse().unwrap();
            let b = ws.next().unwrap().parse().unwrap();
            (a, b)
        };
        v.push(v_i)
    }

    let mut graph = vec![vec![]; n];
    for &(a, b) in &v {
        let a = OneBased(a);
        let b = OneBased(b);
        graph[a.index()].push(b);
        graph[b.index()].push(a);
    }

    let mut edge2index = HashMap::new();
    for (i, &(a, b)) in v.iter().enumerate() {
        edge2index.insert((a, b), i);
    }

    let mut ans = vec![0; n - 1];

    dfs(OneBased(1), &graph, &edge2index, &mut ans);

    // answer
    println!("{}", ans.iter().max().unwrap());
    for x in ans {
        println!("{}", x);
    }
}

#[derive(Debug, Copy, Clone)]
struct OneBased(usize);

impl OneBased {
    fn new(n: usize) -> OneBased {
        if n == 0 {
            panic!("arg n should be positive number");
        }
        OneBased(n)
    }

    fn unwrap(self) -> usize {
        let OneBased(n) = self;
        n
    }

    fn index(self) -> usize {
        let OneBased(n) = self;
        n - 1
    }
}

impl Add for OneBased {
    type Output = OneBased;

    fn add(self, other: OneBased) -> OneBased {
        OneBased::new(self.0 + other.0)
    }
}

// 深さ優先探索（再帰）
fn dfs(
    start: OneBased,
    graph_list: &Graph,
    edge2index: &HashMap<(usize, usize), usize>,
    ans: &mut Vec<usize>,
) {
    let n = graph_list.len();
    let mut visited = vec![false; n];

    dfs_aux(start, 0, graph_list, &mut visited, edge2index, ans);
}

// 補助関数
fn dfs_aux(
    start: OneBased,
    color: usize,
    graph_list: &Graph,
    visited: &mut Vec<bool>,
    edge2index: &HashMap<(usize, usize), usize>,
    ans: &mut Vec<usize>,
) {
    visited[start.index()] = true;

    debugln!("visit {:?}", start);

    let mut next_c = 1;
    for &next in &graph_list[start.index()] {
        let e_index = if start.unwrap() < next.unwrap() {
            *edge2index.get(&(start.unwrap(), next.unwrap())).unwrap()
        } else {
            *edge2index.get(&(next.unwrap(), start.unwrap())).unwrap()
        };
        if !visited[next.index()] {
            if next_c != color {
                ans[e_index] = next_c;
                dfs_aux(next, next_c, &graph_list, visited, edge2index, ans);
            } else {
                next_c += 1;
                ans[e_index] = next_c;
                dfs_aux(next, next_c, &graph_list, visited, edge2index, ans);
            }
            next_c += 1;
        }
    }
}


Measured memory_bytes: 26108