Problem:
Score : 400 points

Problem Statement

Given is a tree G with N vertices.
The vertices are numbered 1 through N, and the i-th edge connects Vertex a_i and Vertex b_i.

Consider painting the edges in G with some number of colors.
We want to paint them so that, for each vertex, the colors of the edges incident to that vertex are all different.

Among the colorings satisfying the condition above, construct one that uses the minimum number of colors.

Constraints

2 \le N \le 10^5

1 \le a_i \lt b_i \le N

All values in input are integers.

The given graph is a tree.

Input

Input is given from Standard Input in the following format:

N
a_1 b_1
a_2 b_2
\vdots
a_{N-1} b_{N-1}

Output

Print N lines.

The first line should contain K, the number of colors used.

The (i+1)-th line (1 \le i \le N-1) should contain c_i, the integer representing the color of the i-th edge, where 1 \le c_i \le K must hold.

If there are multiple colorings with the minimum number of colors that satisfy the condition, printing any of them will be accepted.

Sample Input 1

3
1 2
2 3

Sample Output 1

2
1
2

Sample Input 2

8
1 2
2 3
2 4
2 5
4 7
5 6
6 8

Sample Output 2

4
1
2
3
4
1
1
2

Sample Input 3

6
1 2
1 3
1 4
1 5
1 6

Sample Output 3

5
1
2
3
4
5

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

/* SIMPLE Interactive problem
 * https://codeforces.com/problemset/problem/679/A
 */

/* ID: thanhvq1
LANG: C++14
PROB: namenum
*/

//#pragma GCC optimize ("O2")
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#include<unistd.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
//using namespace __gnu_pbds;
//template <typename T>
//using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

// defines
#define int long long
typedef long long ll;
#define double long double
#define vec vector
#define vi vector<int>
#define vvi vector<vector<int>>
#define ii pair<int, int>
#define vii vector<ii>
#define F first
#define S second
#define MP make_pair
#define PB push_back
#define ALL(x) begin(x),end(x)
#define SZ(x) ((int)(x).size())
#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define FORE(i, a, b) for(int i = (a); i <= (b); i++)
#define FORD(i, a, b) for(int i = (a); i >= (b); i--)
//#define UNI(x) (x).resize(unique((x).begin(), (x).end()) - (x).end());
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),(x))-c.begin())
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define RESET(X, y) memset(X, y, sizeof(X))
#define chkmin(a, b) a = min(a, b)
#define chkmax(a, b) a = max(a, b)
#define max3(a, b, c) max(a, max(b, c))
#define min3(a, b, c) min(a, min(b, c))

//Universal DEBUG: https://codeforces.com/blog/entry/68809
void __print(int x) {cout << x;}
void __print(long x) {cout << x;}
//void __print(long long x) {cout << x;} //invalid if #define int long long
void __print(unsigned x) {cout << x;}
void __print(unsigned long x) {cout << x;}
void __print(unsigned long long x) {cout << x;}
void __print(float x) {cout << x;}
void __print(double x) {cout << x;}
//void __print(long double x) {cout << x;}
void __print(char x) {cout << '\'' << x << '\'';}
void __print(const char *x) {cout << '\"' << x << '\"';}
void __print(const string &x) {cout << '\"' << x << '\"';}
void __print(bool x) {cout << (x ? "true" : "false");}
template<typename T, typename V>
void __print(const pair<T, V> &x) {cout << '{'; __print(x.first); cout << ','; __print(x.second); cout << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cout << '{'; for (auto &i: x) cout << (f++ ? "," : ""), __print(i); cout << "}";}
void _print() {cout << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cout << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define debug(x...) cout << "[" << #x << "] = ["; _print(x)
#else
#define debug(x...)
#endif
/* To debug, just type: debug(x, y, z...). It requires C++ 11 or above.
It can work with: Primitive data types: bool, int, long long, float, ...; pair, string;
Collection types: std::vector, std::map, std::set, ...; Expressions
*/

//permanent constants
const long long INF64 = 1e18; const int INF32 = 1e9; const int BIG = (int)(1e9 + 239);
const int MOD = 1000000007; // (int)1e9+7; //998244353; const ll MOD2 = (ll)MOD * (ll)MOD;
const double PI = 2.0*acos(0.0); //acos(-1.0L);
const double EPS = static_cast<double>(1e-10);
const int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int dx[4] = {0, 1, 0, -1}; const int dy[4] = {1, 0, -1, 0};

//random
mt19937 rnd(239); //(chrono::high_resolution_clock::now().time_since_epoch().count());

typedef vector<vector<int>> matrix;   //matrix Z(n, vector<LL>(n));

/*GRAPH:
	vector<vector<int>> dist; // ma tran dist giua cac dinh
    dist.assign(N, vector<int>(N, INF)); // Khoi tao ma tran dist bang INF
*/
// Sort w Lambda Function: sort(begin(v), end(v), [] (int a, int b) { return a > b; });

void FILEIO() {  freopen("in.txt", "r", stdin);  freopen("out.txt", "w", stdout); }
//void FILEIO() {  freopen("namenum.in", "r", stdin);  freopen("namenum.out", "w", stdout); }
//Tricks:
#define odd(x) ((x) & 1)
#define even(x) !((x) & 1)

int mostSignDigit(int n) { double k = log10(n); return pow(10, k-floor(k));}
int numOfDigits(int n) {return floor(log10(n)) + 1;}
bool isPowerOfTwo(int x) {return x && (!(x&(x-1)));} // first x is for the case x=0

bool allPositive(vector<int> &a) {return all_of(begin(a), end(a), [](int x){return x > 0;});} // are all of the elements positive?
bool anyPositive(vector<int> &a) {return any_of(begin(a), end(a), [](int x){return x > 0;});} // is there at least one positive element?
bool nonePositive(vector<int> &a) {return none_of(begin(a), end(a), [](int x){return x > 0;});} // are none of the elements positive?

//******************

void solve() {
	int n; cin >> n;
	vi adj[n]; map<ii, int> mp;
	FOR(i, 0, n-1) {
		int x, y; cin >> x >> y; x--, y--;
		adj[x].PB(y); adj[y].PB(x);
		mp.insert(MP(MP(x,y), i));
	}

//	debug(mp);

	int mx = INT_MIN; FOR(i, 0, n) mx = max(mx, SZ(adj[i])); // tim degree max

//	debug(mx);

	vi col(n); FOR(i, 0, n) col[i] = 0; // color of edge from cur vertex to parent
	vi ans(n-1, -1); // luu color cua canh thu i
	queue<int> ver; ver.push(0);
	vec<bool> used(n, false); used[0] = true;
//	vi par; par.PB(-1);  // parent of 0
	while(!ver.empty()) {
		int k = ver.front(); ver.pop();
		int startCol = 1; if(col[k] != 0) if(col[k]==1) startCol = 2; // use this color first

//		debug(ans);
//		debug(k, col[k], startCol);

		for(int z : adj[k]) {
			if(used[z]) continue;
			used[z] = true;
			int p = mp[MP(k, z)]; // current edge

//			debug(z, p);

//			if(ans[p]!=-1) continue; // it is edge to parent = colored

//			cout << z << " is not parent" << endl;

			ver.push(z);
			ans[p] = startCol; // dung mau nho nhat trong so con lai
			col[z] = startCol; // luu mau da dung o dinh z

//			debug(ans);
//			debug(col);

			startCol++; if(startCol==col[k]) startCol++; // tranh col[k] da dung
		}
	}
	cout << mx << endl;
	FOR(i, 0, SZ(ans)) {cout << ans[i] << endl;}
}

signed main() {
  ios_base::sync_with_stdio(false); cin.tie();
//  FILEIO();
//  auto beginProgram = chrono::steady_clock::now();

//  int t; cin >> t;
//  FOR(i, 0, t)
  {
//	  cout << "Case #" << i+1 << ": " << solve() << endl;
	  solve();
  }

//  auto endProgram = chrono::steady_clock::now();
//  cout << chrono::duration_cast<chrono::milliseconds>(endProgram - beginProgram).count() << " ms" << endl;

  return 0;
}

//*******************END TEST **************************/