//#pragma warning(disable:4996)
//#include <Windows.h>
#include <iostream>
#include <vector>
#include <limits.h>
#include <algorithm>
#include <string>
#include <math.h>
#include <limits.h>
#include <queue>
#include <map>
#include <set>
#include <iomanip>
#include <bitset>
#include <cassert>
#include <random>
#include <functional>
#include <stack>
#include <iomanip>
#include <cassert>
//#include <boost/multiprecision/cpp_int.hpp>
#include <complex>
#include <cstdio>
#include <list>
#include <bitset>
//#include <stdio.h>

//< in.txt > out.txt
using namespace std;
//std::ios::sync_with_stdio(false);
//std::cin.tie(0);
const long long MOD = 1e9 + 7;
const long long INF = 1e18;
typedef long long LL;
typedef long double LD;
//typedef boost::multiprecision::cpp_int bigint;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PI;
typedef pair<LD, LL> pdl;
typedef pair<LD, LD> pdd;
typedef vector<LL> VLL;
typedef vector<VLL> VVLL;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
typedef unsigned long long ULL;

template<class T>
inline void chmin(T& a, T b) {
	a = min(a, b);
}

template<class T>
inline void chmax(T& a, T b) {
	a = max(a, b);
}

void input();
void solve();

void daminput();

int main() {
	std::cin.tie(0);
	std::ios::sync_with_stdio(false);
	input();
	//daminput();
	solve();
	return 0;
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////

int N;
VI A, B;

void input() {
	cin >> N;
	A.resize(N-1);
	B.resize(N-1);
	for (int n = 0; n < N-1; n++)
	{
		cin >> A[n] >> B[n];
	}
}

void daminput() {
}

template<class T>
struct Gedge {
	int src, to;
	T cost;
	int id;
	Gedge(int s, int t, T c, int i = -1) :src(s), to(t), cost(c), id(i) {}
	Gedge(int t, T c) :src(-1), to(t), cost(c), id(-1) {}
};

template<class T>
using WeightedGraph = vector<vector<Gedge<T>>>;
using UnweightedGraph = vector<vector<LL>>;
template<class T>
using Gedges = vector<Gedge<T>>;

template<class T>
struct TNode {
	int parent;
	VI childs;
	T cost;
	int id;
	TNode() :parent(-1), cost(0), id(-1) {};
};
template<class T>
using Tree = vector<TNode<T>>;

template<class Type>
void SetTree(WeightedGraph<Type>& G, Tree<Type>& T, int root = 0) {
	int N = G.size();
	T.resize(N);
	queue<int> q;
	q.push(root);
	T[root].parent = -1;
	T[root].id = -1;
	T[root].cost = 0;
	while (!q.empty()) {
		int cur = q.front();
		q.pop();
		for (Gedge<Type>& e : G[cur]) {
			if (e.to == T[cur].parent)continue;
			T[e.to].parent = cur;
			T[cur].childs.push_back(e.to);
			T[e.to].id = e.id;
			T[e.to].cost = e.cost;
			q.push(e.to);
		}
	}
}

void solve() {
	VI count(N,0);
	int inoutmax = 0;
	for (int n = 0; n < N-1; n++)
	{
		A[n]--;
		B[n]--;
		count[A[n]]++;
		count[B[n]]++;
		chmax(inoutmax, count[A[n]]);
		chmax(inoutmax, count[B[n]]);
	}
	WeightedGraph<int> G(N);
	for (int n = 0; n < N-1; n++)
	{
		G[A[n]].push_back(Gedge<int>(A[n],B[n],1,n));
		G[B[n]].push_back(Gedge<int>(B[n], A[n], 1, n));
	}
	Tree<int> T;
	SetTree(G, T, 0);
	VI ans(N);
	queue<int> q;
	q.push(0);
	while (!q.empty()) {
		int cur = q.front();
		q.pop();
		int i = 1;
		int par = 0;
		if (T[cur].id != -1)par = ans[T[cur].id];
		for (int ch : T[cur].childs) {
			while (i == par)i++;
			ans[T[ch].id] = i;
			q.push(ch);
			i++;
		}
	}
	cout << inoutmax << "\n";
	for (int n = 0; n < N-1; n++)
	{
		cout << ans[n] << "\n";
	}
}

Measured memory_bytes: 17244