import Foundation

class Scanner {
    static func readInt() -> Int {
        return Int(readLine()!)!
    }
    
    static func readIntArr() -> [Int] {
        return readLine()!.split(separator: " ").map { Int($0)! }
    }
    
    static func readM(_ n: Int) -> [[Int]] {
        var res = [[Int]]()
        for _ in 0..<n {
            res.append(readIntArr())
        }
        return res
    }
    
    static func readUknownIntMat() -> [[Int]] {
        var res = [[Int]]()
        while let line = readLine() {
            res.append(line.split(separator: " ").map { Int($0)! })
        }
        return res
    }
}

let n = Scanner.readInt()
var mat = Scanner.readM(n-1)

var colors = [Int](repeating: 0, count: n)


func solve(_ tree: [[Int]]) -> [Int] {
    var g = [Int: [Int]]()
    for n in tree {
        g[n[0]-1, default: [Int]()].append(n[1]-1)
        g[n[1]-1, default: [Int]()].append(n[0]-1)
    }
    var colors = [Int: [Int: Int]](),
    visited = [Bool](repeating: false, count: n), cols = [Int](repeating: 0, count: n-1)
    visited[0] = true
    
    var mx = 0
    dfs(g, 0, -1, &visited, &colors, &mx)
    
    for (i,n) in tree.enumerated() {
        let dir = colors[n[0]-1, default: [Int: Int]()][n[1]-1, default: 0]
        let rev = colors[n[1]-1, default: [Int: Int]()][n[0]-1, default: 0]
        cols[i] = dir == 0 ? rev : dir
    }
    
    return [mx] + cols
}



func dfs(_ g: [Int: [Int]],
         _ cur: Int,
         _ forbidden: Int,
         _ visited: inout [Bool],
         _ colors: inout [Int: [Int: Int]],
         _ mx: inout Int) {
    var cc = 0
    for c in g[cur, default: [Int]()] {
        guard !visited[c] else {
            continue
        }
        visited[c] = true
        if cc == forbidden {
            cc += 1
        }
        colors[cur, default: [Int: Int]()][c] = (cc+1)
        dfs(g, c, cc, &visited, &colors, &mx)
        cc += 1
    }
    
    mx = max(mx, cc)
}

let res = solve(mat)
for n in res {
    print(n)
}
