#include <bits/stdc++.h>

using namespace std;

vector<int> ans;
int COLOR = 0;


class Edge{
public:
    int id;
    long from, to, cost;
    int color = 0;

    Edge(int i, long f, long t, long c){
        id=i;
        from = f; // 0-indexed
        to = t; // 0-indexed
        cost = c;
    }

    bool operator<(const Edge &e) const{
        if(cost < e.cost){
            return true;
        }
        return false;
    }

    bool operator==(const Edge &e) const{
        if(to == e.to && from == e.from && cost == e.cost){
            return true;
        }
        return false;
    }

    inline bool operator!=(const Edge& e) const{
        return !(*this == e);
    }
};

class Vertex{
public:
    int id; // 0-indexed
    long cost;
    bool visited;
    int from;

    bool operator<(const Vertex &v) const{
        if(cost < v.cost){
            return true;
        }
        return false;
    }

    bool operator==(const Vertex &v) const{
        if(id == v.id){
            return true;
        }
        return false;
    }

    inline bool operator!=(const Vertex& v) const{
        return !(*this == v);
    }

    void reset_vertex(){
        cost = 0;
        visited = false;
        from = 10000000;
    }
};

class Graph{
public:
    int N; // vertices
    int M; // edges
    vector<Vertex> vertex;
    vector < vector < Edge > > edge; // 隣接リスト

    void reset_vertex(){
        for(int i=0; i<N; ++i){
            vertex[i].reset_vertex();
        }
    }
};
Graph graph;

void dfs(Vertex start, int color){
    int l = graph.edge[start.id].size(); // 接続先
    int c = 0;
    for(int i=0; i<l; i++){
        int next = graph.edge[start.id][i].to; // next vertex id
        if(!graph.vertex[next].visited){
            graph.vertex[next].visited = true;
            graph.vertex[next].cost = graph.vertex[start.id].cost + graph.edge[start.id][i].cost;
            graph.vertex[next].from = graph.vertex[start.id].id;
            c++;
            if(c==color){
                c++;
            }
            if(COLOR<c){
                COLOR=c;
            }
            
            ans[graph.edge[start.id][i].id] = c;
            // cout<<"as "<<graph.edge[start.id][i].color<<" "<<graph.edge[start.id][i].id<<endl;
            dfs(graph.vertex[next], ans[graph.edge[start.id][i].id]);
        }
    }
}


int main(){
    
    int from, to;
    cin>>graph.N;
    graph.M = graph.N-1;
    graph.vertex.resize(graph.N);
    graph.edge.resize(graph.N);
    
    // edge init
    for(int i=0; i<graph.M; i++){
        cin>>from>>to;
        // 入力される値の範囲, 0-indexed ?
        from--;
        to--;
        
        graph.edge[from].push_back((Edge){i, from, to, 1});
        // graph.edge[to].push_back((Edge){to, from, 1}); // 無
    }



    // vertex init
    for(int i=0; i<graph.N; i++){
        // graph.vertex[i] = (Vertex){i, 0, false, 0};
        graph.vertex[i].id = i;
        graph.vertex[i].cost = 0;
        graph.vertex[i].visited = false;
        graph.vertex[i].from = 0;
    }
    graph.reset_vertex();

    ans.resize(graph.M);
    // dfs
    for(int i=0; i<graph.N; ++i){
        if(!graph.vertex[i].visited){
            graph.vertex[i].visited = true;
            // ans[i] = 1;
            dfs( graph.vertex[i], 0);
        }
    }
    
    /*
    for(int i=0; i<graph.N; i++){
        int l = graph.edge[i].size();
        for(int j=0; j<l; j++){
            ans[graph.edge[i][j].id] = graph.edge[i][j].color;
        }
    }
    */
    cout<<COLOR<<endl;
    for(int i=0; i<graph.M; ++i){
        cout<<ans[i]<<endl;
    }

    return 0;
}









Measured memory_bytes: 10624