#include <bits/stdc++.h>

#define TYPE(c)   remove_reference_t<decltype(c)>
#define REP(i, n) for(TYPE(n) i = 0; i < n; i++)
#define FOR(v, c) for(TYPE(c.begin()) v = c.begin(); v != c.end(); v++)
#define ALL(c)    c.begin(), c.end()
#define SORT(c)   sort(ALL(c))
#define RSORT(c)  sort(ALL(c), greater<TYPE(c)::value_type>())
#define UNIQUE(c) c.erase(unique(ALL(c)), c.end())

using namespace std;
using ll = long long;

constexpr int MOD  = (int)1e9 + 7;
constexpr int INF  = (int)1e9 + 1;
constexpr ll  LINF = (ll)1e18 + 1;
template<typename T> constexpr bool chmax(T& a, const T& b)
{ if(a < b) { a = b; return true; } else { return false; } }
template<typename T> constexpr bool chmin(T& a, const T& b)
{ if(b < a) { a = b; return true; } else { return false; } }
template<typename S, typename T> ostream& operator<<(ostream &os, const pair<S, T>& p)
{ return os << "(" << p.first << "," << p.second << ")"; }
ostream& operator<<(ostream &os, const string& s)
{ FOR(v, s) os << *v; return os; }
template<typename T> auto operator<<(ostream& os, const T& t)
    -> typename conditional<true, ostream&, decltype(*t.begin())>::type
{ os << "["; FOR(v, t) { if(v != t.begin()) os << ","; os << *v; } os << "]"; return os; }

class Graph {
    using ll = long long;
public:
    enum class Type { Directed, Undirected };
    struct Edge {
        ll   cost{1};
        bool validity{true};
        Edge() = default;
        explicit Edge(const ll& _cost) : cost(_cost) { }
        Edge(const ll& _cost, const bool& _validity) : cost(_cost), validity(_validity) { }
        friend std::ostream& operator <<(std::ostream& os, const Edge& i) {
            os << "cost : " << i.cost << ", " << "validity : " << i.validity; return os;
        }
        friend std::ostream& operator <<(std::ostream& os, const std::shared_ptr<Edge>& i) {
            os << "cost : " << i->cost << ", " << "validity : " << i->validity; return os;
        }
    };
    struct Vertex {
        ll cost{(ll)1e9 + 1};
        explicit Vertex(const ll& _cost) : cost(_cost) { }
        friend std::ostream& operator <<(std::ostream& os, const Vertex& v) {
            os << "cost : " << v.cost; return os;
        }
    };
    const Type edge_type;
    std::vector<Vertex> vertices;
    std::vector<std::map<int, std::shared_ptr<Edge>>> edges;
    Graph(const int&  num_vertex,
          const Type& edge_type,
          const ll& vertex_init_cost = (ll)1e9 + 1) :
        edge_type(edge_type),
        vertices(num_vertex, Vertex(vertex_init_cost)),
        edges(num_vertex) { }
    void setCostToAllVertex(const ll& val) {
        std::fill(vertices.begin(), vertices.end(), Vertex(val));
    };
    void addEdge(const int& src, const int& dst, const ll& cost = 1) {
        auto edge = std::make_shared<Edge>(cost);
        edges[src].emplace(dst, edge);
        if(edge_type == Type::Undirected) edges[dst].emplace(src, edge);
    }
    friend std::ostream& operator <<(std::ostream& os, const Graph& g) {
        os << std::endl
           << "--- Vertex Information ---" << std::endl;
        for(size_t i = 0; i < g.vertices.size(); i++) {
            os << "[[" << i << "] " << g.vertices[i] << "]" << std::endl;
        }
        os << "---- Edge Information ----" << std::endl;
        for(size_t i = 0; i < g.edges.size(); i++) {
            for(const auto& e : g.edges[i]) {
                os << "[[" << i << " -> " << e.first  << "] " << e.second << "]" << std::endl;
            }
        }
        os << "--------------------------";
        return os;
    }
};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    int N;
    std::cin >> N;

    Graph g(N, Graph::Type::Undirected);
    vector<int> deg(N, 0);
    vector<pair<int, int>> in;
    REP(i, N - 1) {
        int a, b;
        std::cin >> a >> b;
        a--; b--;
        deg[a]++;
        deg[b]++;
        in.emplace_back(a, b);
        g.addEdge(a, b, 0);
    }

    auto root_index = distance(deg.begin(), max_element(ALL(deg)));

    auto dfs = [&](auto&& f,
                   const int& index,
                   const int& c,
                   const int& parent_c) -> void {
                   auto new_c =  (parent_c == 1) ? 2 : 1;
                   for(auto& e : g.edges[index]) {
                       if(e.second->cost == 0) {
                           e.second->cost = new_c;
                           new_c += (parent_c != new_c + 1) ? 1 : 2;
                           f(f, e.first, c, e.second->cost);
                       }
                   }
               };

    auto c = 0;
    for(auto& e : g.edges[root_index]) {
        c++;
        e.second->cost = c;
        dfs(dfs, e.first, c, e.second->cost);
    }

    std::cout << c << "\n";
    for(const auto& v : in) {
        std::cout << g.edges[v.first][v.second]->cost << "\n";
    }

    return 0;
}


Measured memory_bytes: 24308