// Original C++ solution (slower):
#include <iostream>

#include <vector>

#include <algorithm>

#include <map>

using namespace std;



struct edge{

    int u, v;

    edge(int u, int v) : u(u), v(v) {}

    bool operator<(const edge& other) const{

        if(u == other.u){

            return v < other.v;

        }

        return u < other.u;

    }

};

vector<int> graph[100005];

vector<edge> edges;

bool num_used[100005];

map<edge, int> colors;



void dfs(int u, int pre = -1, int color = 0){

    int c = color;

    for(int i = 0; i < (int)graph[u].size(); ++i){

        int v = graph[u][i];

        if(v == pre)    continue;

        if(color == 1)    ++c;

        else if(color == 0){

            ++c;

        }

        else{

            if(c == color)  c = 1;

            else if(c == color - 1) c = color + 1;

            else        ++c;

        }

        int tu = u, tv = v;

        if(tu > tv) swap(tu, tv);

        colors[edge(tu, tv)] = c;

        num_used[c] = true;

        dfs(v, u, c);

    }



    return;

}



int main(){

    ios::sync_with_stdio(false);

    cin.tie(nullptr);



    int n;

    cin >> n;

    for(int i = 0; i < n-1; ++i){

        int a, b;

        cin >> a >> b;

        --a, --b;

        if(a > b)   swap(a, b);

        edges.push_back(edge(a, b));

        graph[a].push_back(b);

        graph[b].push_back(a);

    }

    dfs(0);

    int cnt = 0;

    for(int i = 1; i < n; ++i){

        if(num_used[i]) ++cnt;

    }

    cout << cnt << "\n";

    for(int i = 0; i < n-1; ++i){

        cout << colors[edge(edges[i].u, edges[i].v)] << "\n";

    }

}

// Optimized solution to the same problem (faster):
#include <iostream>

#include <vector>

#include <algorithm>

#include <cmath>

#include <queue>

#include <string>

#include <map>

#include <set>

#include <stack>

#include <tuple>

#include <deque>

#include <numeric>

#include <bitset>

#include <iomanip>

#include <cassert>

#include <chrono>

#include <random>

#include <limits>

#include <iterator>

#include <functional>

#include <sstream>

#include <complex>

#include <cstring>

using namespace std;



using ll = long long;

using P = pair<int, int>;

constexpr int INF = 1001001001;

constexpr int mod = 1000000007;

// constexpr int mod = 998244353;



template<class T>

inline bool chmax(T& x, T y){

    if(x < y){

        x = y;

        return true;

    }

    return false;

}

template<class T>

inline bool chmin(T& x, T y){

    if(x > y){

        x = y;

        return true;

    }

    return false;

}



int main(){

    ios::sync_with_stdio(false);

    cin.tie(nullptr);



    int N;

    cin >> N;

    vector<vector<P>> graph(N);

    for(int i = 0; i < N - 1; ++i){

        int a, b;

        cin >> a >> b;

        --a, --b;

        graph[a].emplace_back(b, i);

        graph[b].emplace_back(a, i);

    }

    vector<int> coloring(N - 1, -1);

    int K = 0;

    auto dfs = [&](auto&& self, int from = 0, int par = -1, int prev_color = -1) -> void {

        int color = 0;

        for(auto& p : graph[from]){

            int to = p.first, idx = p.second;

            if(to == par)   continue;

            if(color == prev_color) ++color;

            coloring[idx] = color;

            self(self, to, from, color++);

        }

        chmax(K, color);

    };

    dfs(dfs);

    cout << K << '\n';

    for(int ans : coloring) cout << ans + 1 << '\n';

}

// Fastest known solution for this problem: