You are given a tree consisting of $n$ nodes. You want to write some labels on the tree's edges such that the following conditions hold:

  Every label is an integer between $0$ and $n-2$ inclusive.  All the written labels are distinct.  The largest value among $MEX(u,v)$ over all pairs of nodes $(u,v)$ is as small as possible. 

Here, $MEX(u,v)$ denotes the smallest non-negative integer that isn't written on any edge on the unique simple path from node $u$ to node $v$.


-----Input-----

The first line contains the integer $n$ ($2 \le n \le 10^5$) — the number of nodes in the tree.

Each of the next $n-1$ lines contains two space-separated integers $u$ and $v$ ($1 \le u,v \le n$) that mean there's an edge between nodes $u$ and $v$. It's guaranteed that the given graph is a tree.


-----Output-----

Output $n-1$ integers. The $i^{th}$ of them will be the number written on the $i^{th}$ edge (in the input order).


-----Examples-----
Input
3
1 2
1 3

Output
0
1

Input
6
1 2
1 3
2 4
2 5
5 6

Output
0
3
2
4
1


-----Note-----

The tree from the second sample:

[Image]

Source: codeforces | Difficulty: MEDIUM
Tags: Greedy algorithms

Tree algorithms

Graph traversal

Constructive algorithms


Solutions:
from collections import Counter
import sys
reader = (tuple(map(int, line.split())) for line in sys.stdin)
am = int(input())
bran = list()
for i in range(am - 1):
	bran.append(next(reader))
num_barn = enumerate(bran)
result = []
c = Counter()
for br in bran:
	c[br[0]] += 1
	c[br[1]] += 1
i = 0
best = c.most_common(1)[0]
if best[1] >= 3:
	for br in num_barn:
		if br[1][0] == best[0] or br[1][1] == best[0]:
			result.append((br[0], i))
			i += 1
			if len(result) >= 3:
				break
for j in range(0, am - 1):
	if len(result) != 0 and result[0][0] == j:
		print(result[0][1])
		result.pop(0)
	else:
		print(i)
		i += 1


from collections import defaultdict
n = int(input())
mp = defaultdict(list)
edges = dict()
input_list = []
for i in range(n - 1):
	(a, b) = list(map(int, input().split()))
	(a, b) = (min(a, b), max(a, b))
	edges[a, b] = -1
	input_list.append((a, b))
	mp[a].append(b)
	mp[b].append(a)
solved = False
leaves_edges = []
for i in range(1, n + 1):
	if len(mp[i]) > 2:
		solved = True
		for j in range(len(mp[i])):
			(a, b) = (min(i, mp[i][j]), max(i, mp[i][j]))
			edges[a, b] = j
		break
	elif len(mp[i]) == 1:
		leaves_edges.append((min(i, mp[i][0]), max(i, mp[i][0])))
if not solved:
	for i in range(len(leaves_edges)):
		if edges[leaves_edges[i]] == -1:
			edges[leaves_edges[i]] = i
cnt = n - 2
for e in edges:
	if edges[e] == -1:
		edges[e] = cnt
		cnt -= 1
for i in input_list:
	print(edges[i])


n = int(input())
g = [0] * (n + 1)
l = []
for i in range(n - 1):
	(a, b) = map(int, input().split())
	g[a - 1] += 1
	g[b - 1] += 1
	l.append([a - 1, b - 1])
(cnt, mex) = (0, n - 2)
for (a, b) in l:
	if g[a] == 1 or g[b] == 1:
		print(cnt)
		cnt += 1
	else:
		print(mex)
		mex -= 1


from sys import stdin

def func(arr, l, r, x):
	while l < r:
		mid = (l + r) // 2
		if arr[mid] + x > 0:
			r = mid
		else:
			l = mid + 1
	return l
d = {}
i = 0
n = int(stdin.readline())
for _ in range(n - 1):
	(u, v) = map(int, stdin.readline().split())
	if u in d:
		d[u][0] += 1
		d[u][1].append(i)
	else:
		d[u] = [1, [i]]
	if v in d:
		d[v][0] += 1
		d[v][1].append(i)
	else:
		d[v] = [1, [i]]
	i += 1
ans = [-1] * (n - 1)
val = 0
for ele in d:
	if d[ele][0] >= 3:
		for item in d[ele][1]:
			if ans[item] == -1:
				ans[item] = val
				val += 1
for i in range(n - 1):
	if ans[i] == -1:
		print(val)
		val += 1
	else:
		print(ans[i])


def run():
	n = int(input())
	edges = []
	graph = [0 for i in range(n)]
	for _ in range(n - 1):
		(u, v) = map(int, input().split())
		edges.append([u - 1, v - 1])
		graph[u - 1] += 1
		graph[v - 1] += 1
	for k in range(n):
		if graph[k] >= 3:
			h = 0
			l = graph[k]
			for e in edges:
				if e[0] == k or e[1] == k:
					print(h)
					h += 1
				else:
					print(l)
					l += 1
			return
	for i in range(n - 1):
		print(i)
run()


n = int(input())
g = [[] for i in range(n + 1)]
edges = []
for i in range(n - 1):
	(x, y) = map(int, input().split())
	g[x].append([y, i])
	g[y].append([x, i])
c = 0
indexes = [-1] * (n - 1)
for l in g:
	if len(l) == 1 and indexes[l[0][1]] == -1:
		indexes[l[0][1]] = c
		c += 1
for i in range(len(indexes)):
	if indexes[i] == -1:
		indexes[i] = c
		c += 1
	print(indexes[i])


def main():
	n = int(input())
	turns = []
	dct = dict()
	to_spec = n
	for i in range(n - 1):
		(a, b) = map(int, input().split())
		turns.append((a, b))
		if a in dct:
			if dct[a] == 1:
				dct[a] += 1
				to_spec -= 1
		else:
			dct[a] = 1
		if b in dct:
			if dct[b] == 1:
				dct[b] += 1
				to_spec -= 1
		else:
			dct[b] = 1
	to_add1 = 0
	line = ''
	for i in turns:
		if dct[i[0]] == 1 or dct[i[1]] == 1:
			line += str(to_add1) + '\n'
			to_add1 += 1
		else:
			line += str(to_spec) + '\n'
			to_spec += 1
	print(line)
t = 1
for i in range(t):
	main()


n = int(input())
from collections import defaultdict
d = {}
d1 = defaultdict(list)
ans = [None for i in range(n - 1)]
flag = 0
for i in range(n - 1):
	(a, b) = map(int, input().split())
	d[a, b] = i
	d1[a].append(b)
	d1[b].append(a)
	if len(d1[a]) == 3 and flag == 0:
		if (a, d1[a][0]) in d:
			ans[d[a, d1[a][0]]] = 0
		else:
			ans[d[d1[a][0], a]] = 0
		if (a, d1[a][1]) in d:
			ans[d[a, d1[a][1]]] = 1
		else:
			ans[d[d1[a][1], a]] = 1
		if (a, d1[a][2]) in d:
			ans[d[a, d1[a][2]]] = 2
		else:
			ans[d[d1[a][2], a]] = 2
		flag = 1
	if len(d1[b]) == 3 and flag == 0:
		if (b, d1[b][0]) in d:
			ans[d[b, d1[b][0]]] = 0
		else:
			ans[d[d1[b][0], b]] = 0
		if (b, d1[b][1]) in d:
			ans[d[b, d1[b][1]]] = 1
		else:
			ans[d[d1[b][1], b]] = 1
		if (b, d1[b][2]) in d:
			ans[d[b, d1[b][2]]] = 2
		else:
			ans[d[d1[b][2], b]] = 2
		flag = 1
i = 0
if flag == 1:
	j = 3
else:
	j = 0
while i < len(ans):
	if ans[i] == None:
		ans[i] = j
		j = j + 1
	i = i + 1
for i in ans:
	print(i)


import sys
N = int(input())
if N == 2:
	print(0)
	sys.exit(0)
degree = [0 for _ in range(N + 1)]
adj_list = [[] for _ in range(N + 1)]
edges = []
leaves = []
for _ in range(N - 1):
	[u, v] = list(map(int, input().split()))
	adj_list[u].append(v)
	adj_list[v].append(u)
	edges.append((u, v))
for n in range(1, N + 1):
	if len(adj_list[n]) == 1:
		leaves.append(n)
labels = {}
l0 = leaves[0]
(u0, v0) = (l0, adj_list[l0][0])
labels[u0, v0] = 0
labels[v0, u0] = 0
l1 = leaves[1]
(u1, v1) = (l1, adj_list[l1][0])
labels[u1, v1] = 1
labels[v1, u1] = 1
ctr = 2
if len(leaves) > 2:
	l2 = leaves[-1]
	(u, v) = (l2, adj_list[l2][0])
	labels[u, v] = 2
	labels[v, u] = 2
	ctr += 1
for (u, v) in edges:
	if (u, v) in labels:
		print(labels[u, v])
	else:
		print(ctr)
		ctr += 1


n = int(input())
freqs = [0 for _ in range(n + 1)]
uv = []
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	freqs[u] += 1
	freqs[v] += 1
	uv.append((u, v))
mn = 0
mx = n - 2
for (u, v) in uv:
	if freqs[u] == 1 or freqs[v] == 1:
		print(mn)
		mn += 1
	else:
		print(mx)
		mx -= 1


import sys
input = sys.stdin.readline
N = int(input())
graph = [[] for _ in range(N)]
Edges = {}
for i in range(N - 1):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	graph[a].append(b)
	graph[b].append(a)
	Edges[str(a) + ',' + str(b)] = i
	Edges[str(b) + ',' + str(a)] = i
ans = [-1] * (N - 1)
ind = 0
for n in range(N):
	if len(graph[n]) >= 3:
		for np in graph[n]:
			e = Edges[str(n) + ',' + str(np)]
			ans[e] = ind
			ind += 1
			if ind >= 3:
				break
		break
for n in range(N - 1):
	if ans[n] == -1:
		ans[n] = ind
		ind += 1
print(*ans, sep='\n')


n = int(input())
edges = []
adj_vec = {}
for i in range(n - 1):
	(u, v) = map(int, input().split())
	edges.append([(u, v), -1])
	if u not in adj_vec.keys():
		adj_vec[u] = []
	adj_vec[u].append(v)
	if v not in adj_vec.keys():
		adj_vec[v] = []
	adj_vec[v].append(u)
bamboo = True
for i in range(1, n + 1):
	if len(adj_vec[i]) >= 3:
		mn = i
		bamboo = False
		break
if bamboo:
	for i in range(n - 1):
		print(i)
else:
	cnt = 0
	for i in range(n - 1):
		(u, v) = edges[i][0]
		if u == mn or v == mn:
			edges[i][1] = cnt
			cnt += 1
	for i in range(n - 1):
		if edges[i][1] == -1:
			edges[i][1] = cnt
			cnt += 1
		print(edges[i][1])


import sys
_INPUT_LINES = sys.stdin.read().splitlines()
input = iter(_INPUT_LINES).__next__

def go():
	n = int(input())
	ranks = [0] * n
	e = [0] * n
	for i in range(n - 1):
		(x, y) = map(int, input().split())
		(x, y) = (x - 1, y - 1)
		e[x] = i
		e[y] = i
		ranks[x] += 1
		ranks[y] += 1
	leafs = [i for i in range(n) if ranks[i] == 1]
	if len(leafs) == 2:
		return '\n'.join(map(str, range(n - 1)))
	else:
		vals = [-1] * (n - 1)
		for (ind, i) in enumerate(leafs[:3]):
			j = e[i]
			vals[j] = ind
		ind = 3
		for i in range(n - 1):
			if vals[i] < 0:
				vals[i] = ind
				ind += 1
		return '\n'.join(map(str, vals))
for _ in range(1):
	print(go())


n = int(input())
adj = []
deg = [0 for i in range(n)]
for i in range(n - 1):
	(a, b) = map(int, input().split())
	adj += [[a - 1, b - 1]]
	deg[a - 1] += 1
	deg[b - 1] += 1
op = []
cnt = 0
cnt1 = n - 2
for i in adj:
	if deg[i[0]] == 1 or deg[i[1]] == 1:
		op += [cnt]
		cnt += 1
	else:
		op += [cnt1]
		cnt1 -= 1
for i in op:
	print(i)


from sys import stdin, exit
from itertools import combinations
from collections import deque
input = stdin.readline
lmi = lambda : list(map(int, input().split()))
mi = lambda : map(int, input().split())
si = lambda : input().strip('\n')
ssi = lambda : input().strip('\n').split()
n = int(input())
graph = [[] for i in range(n + 1)]
edges = []
edges2 = {}
for i in range(n - 1):
	(a, b) = mi()
	graph[a].append(b)
	graph[b].append(a)
	edges.append((a, b))
	edges2[a, b] = -1
if all((len(i) <= 2 for i in graph)):
	for i in range(n - 2, -1, -1):
		print(i)
else:
	for (idx, i) in enumerate(graph):
		if len(i) >= 3:
			for j in range(3):
				(a, b) = (idx, graph[idx][j])
				if (a, b) not in edges2:
					(a, b) = (b, a)
				edges2[a, b] = j
			break
	cnt = 3
	for (a, b) in edges2:
		if edges2[a, b] == -1:
			edges2[a, b] = cnt
			cnt += 1
	for (a, b) in edges:
		print(edges2[a, b])


def R():
	return map(int, input().split())

def I():
	return int(input())

def S():
	return str(input())

def L():
	return list(R())
from collections import Counter
import math
import sys
from itertools import permutations
import bisect
n = I()
e = []
deg = [0] * n
for i in range(n - 1):
	(a, b) = R()
	e.append([a - 1, b - 1])
	deg[a - 1] += 1
	deg[b - 1] += 1
x = max(deg)
if x == 2:
	for i in range(n - 1):
		print(i)
	exit()
ind = deg.index(x)
cnt = -1
ans = [0] * (n - 1)
cnt2 = 0
for ed in e:
	(a, b) = ed
	cnt += 1
	if a == ind or b == ind:
		ans[cnt] = cnt2
		cnt2 += 1
cnt = -1
for ed in e:
	(a, b) = ed
	cnt += 1
	if a != ind and b != ind:
		ans[cnt] = cnt2
		cnt2 += 1
print(*ans, sep='\n')


def answer(nodeCount, nodeRelationship):
	if len(nodeRelationship) <= 2:
		return '\n'.join([str(i) for i in range(len(nodeRelationship))])
	graph = [0 for i in range(nodeCount)]
	labelStickers = [i for i in range(len(nodeRelationship) - 1, 2, -1)]
	smallLabelStickers = [0, 1, 2]
	labels = [-1 for i in range(len(nodeRelationship))]
	for i in range(len(nodeRelationship)):
		graph[nodeRelationship[i][0] - 1] += 1
		graph[nodeRelationship[i][1] - 1] += 1
	for i in range(len(graph)):
		if graph[i] >= 3:
			nodeIndex = i + 1
			for j in range(len(nodeRelationship)):
				nr = nodeRelationship[j]
				if (nr[0] == nodeIndex or nr[1] == nodeIndex) and len(smallLabelStickers) > 0:
					labels[j] = smallLabelStickers.pop()
				else:
					labels[j] = labelStickers.pop()
			break
	else:
		labels = labelStickers + smallLabelStickers
	return '\n'.join([str(i) for i in labels])
nodeCount = int(input())
nodeRelationship = [0 for i in range(nodeCount - 1)]
for i in range(nodeCount - 1):
	nodeRelationship[i] = list(map(int, input().split()))
print(answer(nodeCount, nodeRelationship))


import os
import sys
from io import BytesIO, IOBase
import math
from decimal import Decimal
from decimal import *
from collections import defaultdict, deque
import heapq
from decimal import Decimal
getcontext().prec = 25
abcd = 'abcdefghijklmnopqrstuvwxyz'
MOD = pow(10, 9) + 7
BUFSIZE = 8192
from bisect import bisect_left, bisect_right

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
n = int(input())
g = [list() for i in range(n + 1)]
l = []
for i in range(n - 1):
	(x, y) = list(map(int, input().split(' ')))
	g[x].append(y)
	g[y].append(x)
	l.append((x, y))
ans = []
m = 0
mex = n - 2
for i in l:
	if len(g[i[0]]) == 1 or len(g[i[1]]) == 1:
		ans.append(m)
		m += 1
	else:
		ans.append(mex)
		mex -= 1
print(*ans)


n = int(input())
lst = [0] * (n + 1)
s = []
for i in range(n - 1):
	(a, b) = map(int, input().split())
	s.append((a, b))
	lst[a] += 1
	lst[b] += 1
sol = []
left = 0
right = n - 2
for (a, b) in s:
	if lst[a] == 1 or lst[b] == 1:
		print(left)
		left += 1
	else:
		print(right)
		right -= 1


import sys
input = sys.stdin.readline
n = int(input())
E = [[] for i in range(n + 1)]
D = dict()
DEG = [0] * (n + 1)
for i in range(n - 1):
	(x, y) = map(int, input().split())
	E[x].append(y)
	E[y].append(x)
	D[x, y] = i
	D[y, x] = i
	DEG[x] += 1
	DEG[y] += 1
ANS = [-1] * (n - 1)
LIST = []
for i in range(n + 1):
	if DEG[i] == 1:
		LIST.append(i)
if len(LIST) == 2:
	for i in range(n - 1):
		print(i)
else:
	now = 0
	for l in LIST:
		k = E[l][0]
		ANS[D[k, l]] = now
		now += 1
	for i in range(n - 1):
		if ANS[i] == -1:
			ANS[i] = now
			now += 1
	for a in ANS:
		print(a)


n = int(input())
deg = [0 for _ in range(n)]
edges = []
for e in range(n - 1):
	(a, b) = map(int, input().split(' '))
	deg[a - 1] += 1
	deg[b - 1] += 1
	edges.append([a - 1, b - 1])
d3 = -1
for (n, i) in enumerate(deg):
	if i >= 3:
		d3 = n
		break
if d3 == -1:
	for i in range(n):
		print(i)
else:
	curr = deg[d3]
	c2 = 0
	for (n, i) in enumerate(edges):
		if d3 in i:
			print(c2)
			c2 += 1
		else:
			print(curr)
			curr += 1


import sys
input = sys.stdin.buffer.readline

def print(val):
	sys.stdout.write(str(val) + '\n')
from collections import OrderedDict

def prog():
	n = int(input())
	adj_list = [[] for i in range(n + 1)]
	index_edges = OrderedDict()
	for _ in range(n - 1):
		(a, b) = map(int, input().split())
		adj_list[a].append(b)
		adj_list[b].append(a)
		index_edges[a, b] = None
	had3 = False
	for node in range(1, n + 1):
		neighbors = adj_list[node]
		if len(neighbors) >= 3:
			for i in range(3):
				if (node, neighbors[i]) in index_edges:
					index_edges[node, neighbors[i]] = i
				else:
					index_edges[neighbors[i], node] = i
			had3 = True
			break
	if had3:
		curr = 3
		for value in index_edges.values():
			if value is None:
				print(curr)
				curr += 1
			else:
				print(value)
	else:
		curr = 2
		smallest = 0
		for edge in index_edges:
			if len(adj_list[edge[0]]) + len(adj_list[edge[1]]) > 3:
				print(curr)
				curr += 1
			else:
				print(smallest)
				smallest += 1
prog()


from collections import deque
import sys
input = sys.stdin.readline
n = int(input())
g = [[] for x in range(n)]
ed = {}
el = []
for ei in range(n - 1):
	(s, e) = [int(x) for x in input().strip().split()]
	el.append((s, e))
	g[s - 1].append(e - 1)
	g[e - 1].append(s - 1)
nc = [0] * n
v = [0] * n
d = deque()
for node in range(n):
	nc[node] = len(g[node])
	if nc[node] == 1:
		d.append(node)
ce = 0
while d:
	nn = d.popleft()
	v[nn] = 1
	nc[nn] -= 1
	for ni in g[nn]:
		if not v[ni]:
			nc[ni] -= 1
			if nc[ni] == 1:
				d.append(ni)
			ed[ni + 1, nn + 1] = ce
			ed[nn + 1, ni + 1] = ce
			ce += 1
for eli in el:
	print(ed[eli])


n = int(input())
graph = {}
maxi = 1
for i in range(n - 1):
	(u, v) = map(int, input().split())
	if u not in graph:
		graph[u] = {i}
	else:
		graph[u].add(i)
	if v not in graph:
		graph[v] = {i}
	else:
		graph[v].add(i)
	if len(graph[u]) >= 3:
		maxi = u
		break
	if len(graph[v]) >= 3:
		maxi = v
		break
w = 0
t = n - 2
temp = []
for j in range(n - 1):
	if j in graph[maxi]:
		temp.append(str(w))
		w += 1
	else:
		temp.append(str(t))
		t -= 1
print('\n'.join(temp))


from collections import *
from sys import stdin, stdout

class graph:

	def __init__(self, gdict=None):
		if gdict is None:
			gdict = defaultdict(list)
		(self.gdict, self.edges, self.l, self.visit) = (gdict, defaultdict(int), defaultdict(int), defaultdict(int))

	def add_edge(self, node1, node2, w=None):
		self.gdict[node1].append(node2)
		self.gdict[node2].append(node1)
		self.l[node1] += 1
		self.l[node2] += 1

	def bfs_util(self, i):
		(self.visit, self.diam, c, flag) = (defaultdict(int), defaultdict(int), 0, 0)
		(queue, self.visit[i]) = (deque([i]), 1)
		while queue:
			s = queue.popleft()
			for i in self.gdict[s]:
				if self.visit[i] == 0:
					queue.append(i)
					self.visit[i] = 1
					(self.edges[s, i], self.edges[i, s]) = (all[-1], all[-1])
					all.pop()
(edges, n) = ([], int(input()))
g = graph()
for i in range(n - 1):
	(u, v) = map(int, stdin.readline().split())
	g.add_edge(u, v)
	edges.append([u, v])
(all, ans) = ([i for i in range(n - 1)][::-1], [])
g.bfs_util(max(g.l, key=g.l.get))
for (i, j) in edges:
	ans.append(str(g.edges[i, j]))
stdout.write('\n'.join(ans))


from collections import defaultdict as dd
from collections import deque
import sys
sys.setrecursionlimit(pow(10, 5))
input = sys.stdin.readline

def count_leaf(tree, degree, visited, i):
	visited[i] = True
	for k in tree[i]:
		if visited[k] == False:
			degree[i] += 1
			degree[k] += 1
			count_leaf(tree, degree, visited, k)

def main():
	tree = dd(list)
	t = int(input())
	inpu = []
	for i in range(t - 1):
		(a, b) = map(int, input().split())
		inpu.append((a, b))
		tree[a].append(b)
		tree[b].append(a)
	leafes = []
	for i in tree:
		if len(tree[i]) == 1:
			leafes.append(i)
	leaf = deque()
	non_leaf = deque()
	for i in range(len(leafes)):
		leaf.append(i)
	for i in range(len(leafes), t):
		non_leaf.append(i)
	for i in inpu:
		if len(tree[i[0]]) == 1 or len(tree[i[1]]) == 1:
			print(leaf.popleft())
		else:
			print(non_leaf.popleft())
main()


from sys import stdin
input = stdin.readline
import math
n = int(input())
G = [[] for i in range(n + 1)]
for i in range(n - 1):
	(u, v) = map(int, input().split())
	G[u].append([v, i])
	G[v].append([u, i])
ans = [-1] * (n + 1)
for u in range(1, n + 1):
	if len(G[u]) >= 3:
		for j in range(len(G[u])):
			ans[G[u][j][1]] = j
		cnt = len(G[u])
		for j in range(n - 1):
			if ans[j] == -1:
				ans[j] = cnt
				cnt += 1
		for j in range(n - 1):
			print(ans[j])
		return
for i in range(n - 1):
	print(i)


def answer(nodeCount, edges):
	labels = [-1] * len(edges)
	threeAboveConnectedNodeNumber = 0
	labelNumbers = [i for i in range(3, len(edges))]
	mins = [0, 1, 2]
	tree = [[] for _ in range(nodeCount + 1)]
	for i in range(len(edges)):
		(u, v, li) = edges[i]
		tree[u].append(li)
		if len(tree[u]) == 3:
			for j in range(0, 3):
				labels[tree[u][j]] = mins.pop()
			break
		tree[v].append(li)
		if len(tree[v]) == 3:
			for j in range(0, 3):
				labels[tree[v][j]] = mins.pop()
			break
	if len(mins) == 3:
		labels = [i for i in range(len(edges))]
	else:
		for i in range(len(labels)):
			if labels[i] == -1:
				labels[i] = labelNumbers.pop()
	return '\n'.join([str(i) for i in labels])
nodeCount = int(input())
edges = []
for i in range(nodeCount - 1):
	(u, v) = map(int, input().split())
	edges.append([u, v, i])
print(answer(nodeCount, edges))


n = int(input())
degree = [0] * (n + 1)
order = []
for _ in range(n - 1):
	(x, y) = map(int, input().split())
	degree[x] += 1
	degree[y] += 1
	order.append((x, y))
res1 = 0
res2 = n - 2
k = 0
for d in range(n + 1):
	if degree[d] >= 3:
		k = d
for (x, y) in order:
	if x == k or y == k:
		print(res1)
		res1 += 1
	else:
		print(res2)
		res2 -= 1


from sys import stdin
input = stdin.readline
t = int(input())
d = [0 for i in range(t)]
c = [0] * (t + 1)
for i in range(t - 1):
	(u, v) = map(int, input().split())
	c[u] += 1
	c[v] += 1
	d[i] = [u, v]
tgt = 0
for i in range(1, t + 1):
	if c[i] > 2:
		tgt = i
		break
if tgt == 0:
	for i in range(t - 1):
		print(i)
else:
	nums = set(range(3, t - 1))
	count = 0
	for i in range(t - 1):
		if tgt in d[i] and count < 3:
			print(count)
			count += 1
		else:
			print(nums.pop())


from collections import Counter, OrderedDict
from sys import stdin
n = int(stdin.readline())
dct = Counter()
dct1 = OrderedDict()
for _ in range(n - 1):
	x = tuple(map(int, stdin.readline().split()))
	dct1[x] = -1
	dct[x[0]] += 1
	dct[x[1]] += 1
co = 0
for r in dct:
	if dct[r] >= 3:
		for x in dct1:
			if x[0] == r or x[1] == r:
				dct1[x] = co
				co += 1
		break
for r in dct1.keys():
	if dct1[r] == -1:
		dct1[r] = co
		co += 1
for k in dct1.values():
	print(k)


import io
import os
from collections import Counter, defaultdict, deque

def solve(N, edges):
	g = defaultdict(lambda : defaultdict(int))
	for (i, (u, v)) in enumerate(edges):
		g[u][v] = i
		g[v][u] = i
	(maxDeg, maxNode) = max(((len(g[u]), u) for u in g.keys()))
	if maxDeg <= 2:
		return '\n'.join(map(str, range(N - 1)))
	else:
		out = [None for i in range(N - 1)]
		curr = 0
		for (v, index) in g[maxNode].items():
			out[index] = curr
			curr += 1
			if curr == 3:
				break
		for i in range(N - 1):
			if out[i] is None:
				out[i] = curr
				curr += 1
		return '\n'.join(map(str, out))
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
(N,) = [int(x) for x in input().split()]
edges = [[int(x) for x in input().split()] for i in range(N - 1)]
ans = solve(N, edges)
print(ans)


import sys
input = sys.stdin.readline
n = int(input())
sz = [0 for i in range(n + 1)]
ans = [-1 for i in range(n + 1)]
graph = [[] for i in range(n + 1)]
for i in range(n - 1):
	(u, v) = map(int, input().split())
	sz[u] += 1
	sz[v] += 1
	graph[u].append([v, i])
	graph[v].append([u, i])
cur = 0
for i in range(1, n + 1):
	if sz[i] >= 3:
		ans[graph[i][0][1]] = 0
		ans[graph[i][1][1]] = 1
		ans[graph[i][2][1]] = 2
		cur = 3
		break
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = cur
		cur += 1
for i in range(n - 1):
	print(ans[i])


n = int(input())
if n == 2:
	print(0)
	exit()
E = [[] for _ in range(n)]
E_ = [0] * n
ans = [-1] * (n - 1)
for i in range(n - 1):
	(a, b) = map(int, input().split())
	E[a - 1].append([b - 1, i])
	E[b - 1].append([a - 1, i])
	E_[a - 1] += 1
	E_[b - 1] += 1
if max(E_) <= 2:
	x = 0
	for i in range(n):
		if E_[i] == 1:
			ans[E[i][0][1]] = x
			x += 1
	for i in range(n - 1):
		if ans[i] == -1:
			ans[i] = x
			x += 1
else:
	for i in range(n):
		if E_[i] >= 3:
			ans[E[i][0][1]] = 0
			ans[E[i][1][1]] = 1
			ans[E[i][2][1]] = 2
			break
	x = 3
	for i in range(n - 1):
		if ans[i] == -1:
			ans[i] = x
			x += 1
for i in range(n - 1):
	print(ans[i])


import math
import sys
n = int(input())
g = [[] for i in range(n)]
inp = []
for i in range(n - 1):
	(u, v) = map(int, input().split())
	v -= 1
	u -= 1
	inp.append([u, v])
	g[u].append(v)
	g[v].append(u)
right = n - 2
left = 0
for i in range(n - 1):
	if len(g[inp[i][0]]) == 1 or len(g[inp[i][1]]) == 1:
		print(left)
		left += 1
	else:
		print(right)
		right -= 1


n = int(input())
graph = [[] for _ in range(n)]
edges = []
d = dict()
for i in range(n - 1):
	(u, v) = map(int, input().split())
	u -= 1
	v -= 1
	graph[u].append(v)
	graph[v].append(u)
	edges.append((u, v))
	d[u, v] = i
	d[v, u] = i
ans = [None] * (n - 1)
for u in range(n):
	if len(graph[u]) >= 3:
		v1 = graph[u][0]
		v2 = graph[u][1]
		v3 = graph[u][2]
		ans[d[u, v1]] = 0
		ans[d[u, v2]] = 1
		ans[d[u, v3]] = 2
		break
c = 3
for i in range(n - 1):
	if ans[i] is None:
		ans[i] = c % (n - 1)
		c += 1
print('\n'.join(map(str, ans)))


import sys
input = sys.stdin.readline
from collections import defaultdict as dd
n = int(input())
if n == 2:
	print(0)
else:
	d = dd(list)
	res = dd(lambda : -1)
	inp = []
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		d[u].append(v)
		d[v].append(u)
		inp.append((u, v))
	le = []
	for i in range(1, n + 1):
		if len(d[i]) == 1:
			le.append(i)
	cou = 0
	for i in le:
		a = i
		b = d[i][0]
		res[a, b] = cou
		res[b, a] = cou
		cou += 1
	for i in inp:
		if res[i] != -1:
			print(res[i])
		else:
			print(cou)
			cou += 1


import sys
input = sys.stdin.readline
n = int(input())
info = [list(map(int, input().split())) for i in range(n - 1)]
tree = [[] for i in range(n)]
memo = {}
for i in range(n - 1):
	(a, b) = info[i]
	a -= 1
	b -= 1
	if a > b:
		(a, b) = (b, a)
	tree[a].append(b)
	tree[b].append(a)
	memo[a * 1000000 + b] = i
ans = [-1] * (n - 1)
pos = 0
for i in range(n):
	if len(tree[i]) == 1:
		(a, b) = (i, tree[i][0])
		if a > b:
			(a, b) = (b, a)
		ans[memo[a * 1000000 + b]] = pos
		pos += 1
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = pos
		pos += 1
if n == 2:
	print(0)
	exit()
for i in ans:
	print(i)


from __future__ import division, print_function
import os
import sys
from io import BytesIO, IOBase
import collections
if sys.version_info[0] < 3:
	from __builtin__ import xrange as range
	from future_builtins import ascii, filter, hex, map, oct, zip

def solution():
	n = int(input().strip())
	d = collections.defaultdict(int)
	e = []
	for _ in range(n - 1):
		(i, j) = [int(x) for x in input().strip().split(' ')]
		e.append((i, j))
		d[i] += 1
		d[j] += 1
	need = min(3, list(d.values()).count(1))
	if need == 2:
		for i in range(n - 1):
			print(i)
	else:
		cur = 3
		for x in e:
			if d[x[0]] == 1 or d[x[1]] == 1:
				if need == 3:
					print(0)
					need -= 1
				elif need == 2:
					print(1)
					need -= 1
				elif need == 1:
					print(2)
					need -= 1
				else:
					print(cur)
					cur += 1
			else:
				print(cur)
				cur += 1

def main():
	for _ in range(1):
		solution()
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


from math import factorial
from collections import Counter, defaultdict
from heapq import heapify, heappop, heappush
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def RL():
	return map(int, sys.stdin.readline().rstrip().split())

def N():
	return int(input())

def comb(n, m):
	return factorial(n) / (factorial(m) * factorial(n - m)) if n >= m else 0

def perm(n, m):
	return factorial(n) // factorial(n - m) if n >= m else 0

def mdis(x1, y1, x2, y2):
	return abs(x1 - x2) + abs(y1 - y2)
mod = 1000000007
INF = float('inf')

def main():
	n = N()
	rec = [0] * (n + 1)
	gp = defaultdict(list)
	pres = []
	rnode = -1
	for _ in range(n - 1):
		(a, b) = RL()
		pres.append((a, b))
		gp[a].append(b)
		gp[b].append(a)
		rec[a] += 1
		rec[b] += 1
		if rec[a] == 3:
			rnode = a
		if rec[b] == 3:
			rnode = b
	if rnode == -1:
		for i in range(n - 1):
			print(i)
	else:
		(pb, pe) = (0, n - 2)
		for (a, b) in pres:
			if a == rnode or b == rnode:
				print(pb)
				pb += 1
			else:
				print(pe)
				pe -= 1
main()


from sys import stdin
from collections import defaultdict
input = stdin.readline

def read_tuple():
	return map(int, input().split())

def read_int():
	return int(input())

def read_list():
	return list(map(int, input().split()))

def read_str_list():
	return list(input().split())
n = read_int()
tree = defaultdict(list)
queries = []
for _ in range(n - 1):
	(u, v) = read_tuple()
	tree[u].append(v)
	tree[v].append(u)
	if u > v:
		(u, v) = (v, u)
	queries.append((u, v))
ans = defaultdict(int)
mex = 0
for u in range(1, n + 1):
	if len(tree[u]) == 1 and mex < n - 1:
		v = tree[u][0]
		if u > v:
			ans[v, u] = mex
		else:
			ans[u, v] = mex
		mex += 1
for (u, v) in queries:
	val = ans.get((u, v), -1)
	if val == -1:
		print(mex)
		mex += 1
	else:
		print(val)


t = int(input())
count = [0] * 100005
a = []
for j in range(t - 1):
	(x1, x2) = map(int, input().split())
	count[x1] += 1
	count[x2] += 1
	a.append([x1, x2])
k = 0
l = t - 2
ans = []
for i in range(len(a)):
	if count[a[i][0]] == 1 or count[a[i][1]] == 1:
		ans.append(k)
		k += 1
	else:
		ans.append(l)
		l -= 1
for i in range(len(ans)):
	print(ans[i])


from sys import stdin
inf = stdin
n = int(inf.readline())
arr = [0] * (n + 1)
ll = []
for qw in range(n - 1):
	(a, b) = map(int, inf.readline().split(' '))
	ll.append([a, b])
	arr[a] += 1
	arr[b] += 1
count = 0
for i in range(n + 1):
	if arr[i] == 1:
		count += 1
count1 = count
count -= 1
if n != 2:
	for i in range(n - 1):
		a = ll[i][0]
		b = ll[i][1]
		if arr[a] == 1 or arr[b] == 1:
			print(count)
			count -= 1
		else:
			print(count1)
			count1 += 1
else:
	print(0)


N = int(input())
FA = [0] * N
edges = []
for n in range(N - 1):
	edges.append(list(map(int, input().split())))
	FA[edges[n][0] - 1] += 1
	FA[edges[n][1] - 1] += 1
leaf = {}
for i in range(N):
	if FA[i] == 1:
		leaf.update({i + 1: 1})
val = 0
ans = []
for e in edges:
	if e[0] in leaf.keys() or e[1] in leaf.keys():
		ans.append(val)
		val += 1
	else:
		ans.append(-1)
for i in range(N - 1):
	if ans[i] == -1:
		ans[i] = val
		val += 1
for i in range(N - 1):
	print(ans[i])


n = int(input())
c = [0] * 100005
q = []
for i in range(n - 1):
	(a, b) = map(int, input().split())
	c[a] += 1
	c[b] += 1
	q.append([a, b])
x = 0
y = n - 2
res = []
for i in range(len(q)):
	if c[q[i][0]] == 1 or c[q[i][1]] == 1:
		res.append(x)
		x += 1
	else:
		res.append(y)
		y -= 1
for i in res:
	print(i)


import sys
input = sys.stdin.readline
from collections import defaultdict
n = int(input())
tree = defaultdict(list)
store = []
for i in range(n - 1):
	(u, v) = map(int, input().split())
	store.append((u, v))
	tree[u].append(v)
	tree[v].append(u)
(leave, unleave) = (0, n - 2)
for i in range(len(store)):
	if len(tree[store[i][0]]) == 1:
		print(leave)
		leave += 1
	elif len(tree[store[i][1]]) == 1:
		print(leave)
		leave += 1
	else:
		print(unleave)
		unleave -= 1


import collections
import sys
adj = {}
n = int(sys.stdin.readline())
temp = []
for _ in range(n - 1):
	(a, b) = sys.stdin.readline().split()
	a = int(a)
	b = int(b)
	temp.append(tuple(sorted((a, b))))
	if a in adj:
		adj[a].append(b)
	else:
		adj[a] = [b]
	if b in adj:
		adj[b].append(a)
	else:
		adj[b] = [a]
m = 0
for i in adj.keys():
	if len(adj[i]) > m:
		m = len(adj[i])
		root = i
vis = set()
vis.add(root)
q = collections.deque([root])
mex = 0
ans = {}
while len(q) != 0:
	head = q.popleft()
	for edge in adj[head]:
		if edge not in vis:
			ans[tuple(sorted((head, edge)))] = mex
			mex += 1
			vis.add(edge)
			q.append(edge)
for i in temp:
	sys.stdout.write(str(ans[i]))
	sys.stdout.write('\n')


import sys
input = sys.stdin.readline

def getInt():
	return int(input())

def getVars():
	return map(int, input().split())

def getList():
	return list(map(int, input().split()))

def getStr():
	return input().strip()

def foo(k, ii):
	global d, res3, res, num
	if k not in d:
		d[k] = []
	d[k].append(ii)
	if len(d[k]) == 3 and len(res3) == 0:
		res3 = d[k].copy()
n = getInt()
res3 = []
d = {}
num = n - 2
for i in range(n - 1):
	(u, v) = getVars()
	foo(u, i)
	foo(v, i)
num = n - 2
num3 = 0
for i in range(n - 1):
	if i in res3:
		print(num3)
		num3 += 1
	else:
		print(num)
		num -= 1


n = int(input())
zoznam = [[] for i in range(n)]
for i in range(n - 1):
	(a, b) = map(int, input().split())
	zoznam[a - 1].append((b, i))
	zoznam[b - 1].append((a, i))
a = -1
for i in range(n):
	if len(zoznam[i]) >= 3:
		a = i
		break
if a == -1:
	for i in range(n - 1):
		print(i)
else:
	teraz = 0
	rip = 3
	for i in range(n - 1):
		if i == zoznam[a][0][1] or i == zoznam[a][1][1] or i == zoznam[a][2][1]:
			print(teraz)
			teraz += 1
		else:
			print(rip)
			rip += 1


data = input().rstrip().split()
n = int(data[0])
edges = []
g = {i + 1: [] for i in range(n)}
leafes = set()
for _ in range(n - 1):
	data = input().rstrip().split()
	(a, b) = (int(data[0]), int(data[1]))
	(a, b) = sorted([a, b])
	edges.append((a, b))
	g[a].append(b)
	g[b].append(a)
for (k, v) in g.items():
	if len(leafes) == 3:
		break
	if len(v) == 1:
		e = sorted([k, v[0]])
		leafes.add(tuple(e))
counter = len(leafes)
l_counter = 0
to_print = []
for edge in edges:
	(a, b) = edge
	if edge in leafes:
		to_print.append(l_counter)
		l_counter += 1
	else:
		to_print.append(counter)
		counter += 1
for p in to_print:
	print(p)


n = int(input())
s = [[] for _ in range(n + 1)]
inp = []
for _ in range(n - 1):
	(a, b) = map(int, input().split())
	inp.append(sorted([a, b]))
	s[a].append(b)
	s[b].append(a)
ind0 = 0
ind1 = 0
ind2 = 0
for i in range(1, n + 1):
	if len(s[i]) == 1:
		if not ind0:
			ind0 = sorted([i, s[i][0]])
		elif not ind1:
			ind1 = sorted([i, s[i][0]])
		else:
			ind2 = sorted([i, s[i][0]])
			break
ans = []
j = 2
if ind2:
	j = 3
for i in inp:
	if i == ind0:
		ans.append('0')
	elif i == ind1:
		ans.append('1')
	elif i == ind2:
		ans.append('2')
	else:
		ans.append(str(j))
		j += 1
print('\n'.join(ans))


import sys
readline = sys.stdin.readline
ns = lambda : readline().rstrip()
ni = lambda : int(readline().rstrip())
nm = lambda : map(int, readline().split())
nl = lambda : list(map(int, readline().split()))

def solve():
	n = ni()
	if n == 2:
		print(0)
		return
	edges = [tuple(nm()) for _ in range(n - 1)]
	ans = [-1] * (n - 1)
	G = [list() for _ in range(n)]
	for (i, (u, v)) in enumerate(edges):
		u -= 1
		v -= 1
		G[u].append((i, v))
		G[v].append((i, u))
	c = 0
	for i in range(n):
		if len(G[i]) == 1:
			ans[G[i][0][0]] = c
			c += 1
	for i in range(n - 1):
		if ans[i] < 0:
			ans[i] = c
			c += 1
	print(*ans, sep='\n')
	return
solve()


n = int(input())
order = []
adj = [[] for i in range(n)]
tel = {}
for i in range(n - 1):
	(a, b) = [int(s) - 1 for s in input().split()]
	order.append((a, b))
	tel[a, b] = -1
	tel[b, a] = -1
	adj[a].append(b)
	adj[b].append(a)
count = 0
ind = -1
for i in range(n):
	if len(adj[i]) >= 3:
		for j in adj[i]:
			tel[i, j] = count
			tel[j, i] = count
			count += 1
		ind = i
		break
for i in range(n):
	if i != ind:
		for j in adj[i]:
			if tel[i, j] == -1:
				tel[i, j] = count
				tel[j, i] = count
				count += 1
for i in range(n - 1):
	print(tel[order[i][0], order[i][1]])


n = int(input())
tree = [0] * (n + 1)
edges = []
for i in range(n - 1):
	(u, v) = map(int, input().split())
	edges.append((u, v))
	tree[u] += 1
	tree[v] += 1
left = 0
right = n - 2
for (u, v) in edges:
	if tree[u] == 1 or tree[v] == 1:
		print(left)
		left += 1
	else:
		print(right)
		right -= 1


N = int(input())
edges = []
in_node = [0] * N
for _ in range(N - 1):
	(a, b) = map(int, input().split())
	in_node[a - 1] += 1
	in_node[b - 1] += 1
	edges.append([a - 1, b - 1])
leaf = {i for (i, v) in enumerate(in_node) if v == 1}
num = 0
ids = [-1] * (N - 1)
for i in range(N - 1):
	(a, b) = edges[i]
	if a in leaf or b in leaf:
		ids[i] = num
		num += 1
for i in range(N - 1):
	(a, b) = edges[i]
	if ids[i] == -1:
		ids[i] = num
		num += 1
print('\n'.join(map(str, ids)))


n = int(input())
vec = [[] for i in range(n + 1)]
d = {}
li = [-1] * (n - 1)
for i in range(n - 1):
	(a, b) = map(int, input().split())
	vec[a].append([b, i])
	vec[b].append([a, i])
	d[a, b] = 0
mx = max([len(vec[i]) for i in range(n)])
c = 0
for i in range(n):
	if len(vec[i]) > 2:
		for j in vec[i]:
			li[j[1]] = c
			c += 1
		break
for i in range(n):
	for j in vec[i]:
		if li[j[1]] == -1:
			li[j[1]] = c
			c += 1
for i in li:
	print(i)


import sys

def inp():
	return sys.stdin.readline()
n = int(inp())
el = []
deg = [0] * (n + 1)
edge = {}
ans_edge = {}
for _ in range(n - 1):
	(u, v) = map(int, inp().split())
	el.append((u, v))
	deg[u] += 1
	deg[v] += 1
	if u not in edge:
		edge[u] = set()
	if v not in edge:
		edge[v] = set()
ll = [(min(deg[i[1]], deg[i[0]]), max(deg[i[1]], deg[i[0]]), i) for i in el]
ll.sort(reverse=True)
val = 0
while val < n - 1:
	rmv = ll.pop()
	vtx = rmv[1]
	ans_edge[rmv[2]] = val
	val += 1
for i in el:
	print(ans_edge[i])


from collections import defaultdict
n = int(input())
d2 = {}
ans = {}
d2 = defaultdict(lambda : [], d2)
ans = defaultdict(lambda : -1, ans)
if n == 2:
	(u, v) = map(int, input().split(' '))
	print(0)
else:
	b = []
	for i in range(n - 1):
		(u, v) = map(int, input().split(' '))
		b.append((u, v))
		d2[u].append(v)
		d2[v].append(u)
	arr = []
	a = [0] * (n + 1)
	for i in range(1, n + 1):
		if len(d2[i]) == 1:
			arr.append(i)
	k = 0
	for i in arr:
		ans[d2[i][0], i] = k
		ans[i, d2[i][0]] = k
		k += 1
	ans1 = [0] * (n - 1)
	t = 0
	for i in b:
		ans1[t] = ans[i]
		t += 1
	i = 0
	while i < n - 1:
		if ans1[i] == -1:
			ans1[i] = k
			k += 1
		i += 1
	for i in ans1:
		print(i)


n = int(input())
if n == 2:
	(a, b) = [int(i) for i in input().split()]
	print(0)
	exit(0)
r = [[] for i in range(n - 1)]
K = [0 for i in range(n)]
for i in range(n - 1):
	(a, b) = [int(i) for i in input().split()]
	r[i] = [a - 1, b - 1]
	K[a - 1] += 1
	K[b - 1] += 1
s = set()
for i in range(len(K)):
	if K[i] == 1:
		s.add(i)
		if len(s) > 3:
			break
k = 0
if len(s) <= 2:
	l = 2
	f = 2
else:
	l = 3
	f = 3
for (a, b) in r:
	if (a in s or b in s) and k < f:
		print(k)
		k += 1
	else:
		print(l)
		l += 1


n = int(input())
edges = []
degrees = [0]
for i in range(n):
	degrees.append(0)
output = []
for i in range(n - 1):
	output.append(-1)

def d3():
	d3_vertex = 0
	for i in range(n + 1):
		if degrees[i] > 2:
			d3_vertex = i
	return d3_vertex
for i in range(n - 1):
	inp = input().split()
	inp = [int(i) for i in inp]
	inp.sort()
	edges.append(inp)
	degrees[inp[0]] = degrees[inp[0]] + 1
	degrees[inp[1]] = degrees[inp[1]] + 1
f = d3()
if f > 0:
	u = 0
	for i in range(n - 1):
		if edges[i][0] == f or edges[i][1] == f:
			output[i] = u
			u = u + 1
	for i in range(n - 1):
		if output[i] == -1:
			output[i] = u
			u = u + 1
	for i in range(n - 1):
		print(output[i])
else:
	for i in range(n - 1):
		print(i)


import sys
input = sys.stdin.readline
from collections import deque, defaultdict

def bfs(s):
	visited = [False] * n
	visited[s] = True
	q = deque([s])
	c = 0
	while q:
		v = q.popleft()
		for nv in G[v]:
			if not visited[nv]:
				k = min(v, nv) * 10 ** 6 + max(v, nv)
				ans[k] = c
				visited[nv] = True
				q.append(nv)
				c += 1
n = int(input())
d = [0] * n
G = [[] for _ in range(n)]
edges = []
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	d[u - 1] += 1
	d[v - 1] += 1
	G[u - 1].append(v - 1)
	G[v - 1].append(u - 1)
	edges.append((min(u - 1, v - 1), max(u - 1, v - 1)))
ans = defaultdict(int)
for i in range(n):
	if d[i] >= 3:
		mark = i
		break
else:
	mark = 0
bfs(mark)
for (u, v) in edges:
	print(ans[u * 10 ** 6 + v])


from sys import stdin
from collections import Counter

def solve(n, es):
	label = [-1] * (n - 1)
	c = Counter([x for p in es for x in p])
	m = len(list(filter(lambda x: x == 1, c.values())))
	(L, R) = (0, m)
	for (idx, uv) in enumerate(es):
		(u, v) = uv
		if c[u] == 1 or c[v] == 1:
			label[idx] = L
			L += 1
		else:
			label[idx] = R
			R += 1
	print('\n'.join([str(l) for l in label]))
n = int(input())
es = [tuple(map(int, line.split())) for line in stdin]
solve(n, es)


def main():
	import sys
	input = sys.stdin.buffer.readline
	N = int(input())
	adj = [[] for _ in range(N + 1)]
	E = {}
	for i in range(N - 1):
		(a, b) = map(int, input().split())
		adj[a].append(b)
		adj[b].append(a)
		E[a * (N + 1) + b] = i
		E[b * (N + 1) + a] = i
	flg = 0
	ans = [-1] * (N - 1)
	for v in range(1, N + 1):
		if len(adj[v]) >= 3:
			for (i, u) in enumerate(adj[v][:3]):
				ans[E[u * (N + 1) + v]] = i
			flg = 1
			break
	if flg:
		j = 3
		for i in range(N - 1):
			if ans[i] == -1:
				ans[i] = j
				j += 1
	else:
		ans = list(range(N - 1))
	print('\n'.join(map(str, ans)))
main()


n = int(input())
(cc, ls) = ([0] * (n + 1), [])
for _ in range(n - 1):
	(a, b) = map(int, input().split())
	ls.append((a, b))
	cc[a] += 1
	cc[b] += 1
if n == 2:
	print(0)
	exit()
r = 0
for (k, v) in enumerate(cc):
	if v >= 3:
		r = k
		break
idx = 3 if r > 0 else 0
(rcc, res) = (0, [])
for (a, b) in ls:
	if rcc < 3 and (a == r or b == r):
		res.append(rcc)
		rcc += 1
	else:
		res.append(idx)
		idx += 1
for rs in res:
	print(rs)


import sys

def fastio():
	from io import StringIO
	from atexit import register
	global input
	sys.stdin = StringIO(sys.stdin.read())
	input = lambda : sys.stdin.readline().rstrip('\r\n')
	sys.stdout = StringIO()
	register(lambda : sys.__stdout__.write(sys.stdout.getvalue()))
fastio()
INF = 10 ** 20
MOD = 10 ** 9 + 7
I = lambda : list(map(int, input().split()))
from math import gcd
from math import ceil
from collections import defaultdict as dd, Counter
from bisect import bisect_left as bl, bisect_right as br
(n,) = I()
g = [[] for i in range(n)]
edges = dd(int)
d = [0] * n
for i in range(n - 1):
	(x, y) = I()
	x -= 1
	y -= 1
	g[x].append(y)
	g[y].append(x)
	if y < x:
		(x, y) = (y, x)
	edges[x, y] = i
	d[x] += 1
	d[y] += 1
ans = [-1] * n
v = dd(int)
mex = 0
if n == 2:
	print(0)
	exit()
for i in range(n):
	if d[i] == 1:
		e = tuple(sorted([i, g[i][0]]))
		ans[edges[e]] = mex
		mex += 1
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = mex
		mex += 1
	print(ans[i])


from collections import defaultdict

class Graph:

	def __init__(self, V):
		self.vertices = V
		self.graph = defaultdict(list)
		self.degree = defaultdict(int)
		self.label = defaultdict(int)
		self.edges = []

	def add_edge(self, u, v):
		self.graph[u].append(v)
		self.graph[v].append(u)
		self.degree[u] += 1
		self.degree[v] += 1
		self.label[u, v] = -1
		self.edges.append((u, v))
n = int(input())
g = Graph(n)
for _ in range(n - 1):
	(u, v) = map(int, input().strip().split())
	g.add_edge(u, v)
g.degree = dict(sorted(g.degree.items(), key=lambda x: x[1]))
ass_label = 0
for (key, val) in g.degree.items():
	if val > 1:
		break
	for node in g.graph[key]:
		if (key, node) in g.label and g.label[key, node] == -1:
			g.label[key, node] = ass_label
			ass_label += 1
		elif g.label[node, key] == -1:
			g.label[node, key] = ass_label
			ass_label += 1
for edge in g.edges:
	if g.label[edge] != -1:
		print(g.label[edge])
	else:
		print(ass_label)
		ass_label += 1


import sys
reader = (s.rstrip() for s in sys.stdin)
input = reader.__next__
n = int(input())
dic = {}
seq = {}
for i in range(n - 1):
	(u, v) = list(map(int, input().split()))
	ulist = dic.get(u, [])
	vlist = dic.get(v, [])
	ulist.append(v)
	vlist.append(u)
	dic[u] = ulist
	dic[v] = vlist
	seq[u, v] = i
ans = [-1] * (n - 1)
curr = 0
for lis in dic:
	nodes = dic[lis]
	if len(nodes) == 1:
		seqloc = seq.get((lis, dic[lis][0]), False)
		seqloc1 = seq.get((dic[lis][0], lis), False)
		if seqloc:
			ans[seqloc] = curr
			curr += 1
		elif seqloc1:
			ans[seqloc1] = curr
			curr += 1
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = curr
		curr += 1
for an in ans:
	print(an)


import sys
from sys import stdin, stdout
n = int(input())
edges = []
g = [[] for i in range(n)]
x = -1
for i in range(n - 1):
	(u, v) = map(int, sys.stdin.readline().split(' '))
	u -= 1
	v -= 1
	if u > v:
		(u, v) = (v, u)
	g[u].append(v)
	g[v].append(u)
	if len(g[u]) > 2:
		x = u
	if len(g[v]) > 2:
		x = v
	edges.append((u, v))
ans = {}
if x == -1:
	for i in range(n - 1):
		print(i)
else:
	i = 0
	for v in g[x]:
		if v > x:
			ans[x, v] = i
		else:
			ans[v, x] = i
		i += 1
	for e in edges:
		if e in ans:
			print(ans[e])
		else:
			print(i)
			i += 1


import sys
import math

def get_array():
	return list(map(int, sys.stdin.readline().strip().split()))

def read():
	return int(input())

def reads():
	return map(int, sys.stdin.readline().strip().split())

def input():
	return sys.stdin.readline().strip()
to = [0] * 102000
st = [0] * 102000
res = [0] * 102000
idx = [0] * 102000
n = read()
for i in range(1, n):
	(x, y) = reads()
	to[x] += 1
	to[y] += 1
	idx[x] = i
	idx[y] = i
tot = 0
for i in range(1, n + 1):
	if to[i] == 1 and st[idx[i]] == 0:
		res[idx[i]] = tot
		st[idx[i]] = 1
		tot += 1
for i in range(1, n):
	if st[i] == 0:
		res[i] = tot
		tot += 1
for i in range(1, n):
	print(res[i], end=' ')


n = int(input())
a = []
g = []
dic = {}
for i in range(n):
	g.append([])
for i in range(n - 1):
	(u, v) = map(int, input().split())
	a.append((u - 1, v - 1))
	g[u - 1].append(v - 1)
	g[v - 1].append(u - 1)
s = 0
for i in range(len(g)):
	if len(g[i]) >= 3:
		u = i
		s = 0
		for v in g[i]:
			dic[u, v] = s
			dic[v, u] = s
			s += 1
		break
if s == 0:
	for i in range(n - 1):
		print(i)
else:
	for i in a:
		if i in dic:
			print(dic[i])
		else:
			print(s)
			s += 1


import sys
input = sys.stdin.readline
(N,) = map(int, input().split())
G = [set() for _ in range(N + 1)]
for i in range(N - 1):
	(a, b) = map(int, input().split())
	G[a].add((b, i))
	G[b].add((a, i))
if N == 2:
	print(0)
	sys.exit()
stack = [1]
vs = set([1])
d = [-1 for _ in range(N + 1)]
cc = [0 for _ in range(N + 1)]
while stack:
	v = stack.pop()
	for (u, j) in G[v]:
		if u in vs:
			continue
		d[u] = j
		cc[v] += 1
		vs.add(u)
		stack.append(u)
if cc[1] == 1:
	cc[1] = 0
	d[1] = G[1].pop()[1]
rs = [-1 for _ in range(N - 1)]
k = 0
for i in range(1, N + 1):
	if cc[i] == 0:
		rs[d[i]] = k
		k += 1
for i in range(N - 1):
	if rs[i] == -1:
		rs[i] = k
		k += 1
print(*rs)


from sys import stdin
d = {}
pair = []
l = int(stdin.readline())
v = [-1] * (l - 1)
for _ in range(l - 1):
	n = [int(i) for i in stdin.readline().split(' ')]
	pair.append(n)
	(key1, key2) = (str(n[0]), str(n[1]))
	if key1 not in d:
		d[key1] = 1
	else:
		d[key1] += 1
	if key2 not in d:
		d[key2] = 1
	else:
		d[key2] += 1
values = list(d.values())
values = list(sorted(set(values)))
flag = 0
for (key, value) in d.items():
	if value > 2:
		flag = 1
		temp1 = 0
		temp2 = 3
		key = int(key)
		for i in range(l):
			if pair[i][0] == key or pair[i][1] == key:
				v[i] = temp1
				temp1 += 1
				if temp1 > 2:
					break
		for i in range(l - 1):
			if v[i] != -1:
				print(v[i])
			else:
				print(temp2)
				temp2 += 1
		break
if flag == 0:
	for i in range(0, l - 1):
		print(i)


import sys
from math import *
from collections import defaultdict
from queue import deque
from heapq import heappush, heappop
lines = [line.strip() for line in sys.stdin.readlines()]
n = int(lines[0])
ret = [-1 for i in range(n - 1)]
edges = []
deg = [0 for i in range(n)]
for i in range(1, n):
	(v, u) = list(map(int, lines[i].split()))
	v -= 1
	u -= 1
	edges += [(v, u)]
	deg[v] += 1
	deg[u] += 1
cnt = 0
for i in range(n - 1):
	if deg[edges[i][0]] == 1 or deg[edges[i][1]] == 1:
		ret[i] = cnt
		cnt += 1
for i in range(n - 1):
	if ret[i] == -1:
		ret[i] = cnt
		cnt += 1
for x in ret:
	print(x)


n = int(input())
d = [0] * (n + 1)
arr = []
for i1 in range(n - 1):
	(c1, c2) = list(map(int, input().split()))
	d[c1] += 1
	d[c2] += 1
	arr.append([c1, c2])
start = 0
end = n - 2
for i1 in range(n - 1):
	if d[arr[i1][0]] == 1 or d[arr[i1][1]] == 1:
		print(start)
		start += 1
	else:
		print(end)
		end -= 1


class Solution:

	def __init__(self):
		pass

	def s(self):
		n = int(input())
		c = {}
		edges = []
		(f, l) = (0, n - 2)
		for i in range(n - 1):
			(u, v) = map(int, input().split())
			edges.append((u, v))
			c.setdefault(u, 0)
			c.setdefault(v, 0)
			c[u] += 1
			c[v] += 1
		for i in edges:
			if c[i[0]] == 1 or c[i[1]] == 1:
				print(f)
				f += 1
			else:
				print(l)
				l -= 1
c = Solution()
c.s()


from collections import defaultdict, deque
from sys import stdin, stdout
(n, A) = (int(input()), [])
for _i in range(n - 1):
	A.append(tuple((int(x) for x in stdin.readline().strip().split(' '))))
hmap = defaultdict(list)
for (a, b) in A:
	hmap[a].append(b)
	hmap[b].append(a)
res = dict()
label = 0
for i in range(1, n + 1):
	if len(hmap[i]) >= 3:
		for x in hmap[i]:
			res[i, x] = label
			res[x, i] = label
			label += 1
		break
for x in A:
	if x not in res.keys():
		stdout.write(str(label) + '\n')
		label += 1
	else:
		stdout.write(str(res[x]) + '\n')


import functools, sys

def ip():
	n = int(sys.stdin.readline())
	g = []
	for _ in range(n):
		g.append(set())
	d = {}
	for j in range(n - 1):
		(u, v) = map(int, sys.stdin.readline().split())
		u -= 1
		v -= 1
		d[min(u, v), max(u, v)] = j
		g[u].add(v)
		g[v].add(u)
	k = [i for i in range(n)]

	def myfun(u, v):
		return len(g[u]) - len(g[v])
	k = sorted(k, key=functools.cmp_to_key(myfun))
	ans = [0] * (n - 1)
	curr = 0
	while curr < n - 1:
		if len(k) == 0:
			break
		u = k.pop()
		if len(g[u]) == 0:
			continue
		while g[u]:
			v = g[u].pop()
			g[v].remove(u)
			t = (min(u, v), max(u, v))
			ans[d[t]] = curr
			curr += 1
	for i in ans:
		print(i)
ip()


n = int(input())
links = [set([]) for i in range(n)]
paths = []
for i in range(n - 1):
	(In, Out) = input().split(' ')
	links[int(In) - 1].add(i)
	links[int(Out) - 1].add(i)
out = [0] * (n - 1)
k = 0
links.sort(key=len)
done = set([])
for i in range(n - 1):
	for j in links[i]:
		if j not in done:
			done.add(j)
			out[j] = str(k)
			k += 1
for i in out:
	print(i)


N = int(input())
g = {i: [] for i in range(N + 1)}
dist = [2 ** 20 for _ in range(N + 1)]
visited = [0] * (N + 1)
s = [1]
E = []
for num in range(N - 1):
	(u, v) = list(map(int, input().split()))
	g[u].append(v)
	g[v].append(u)
	E.append((u, v))
for i in range(1, N + 1):
	if len(g[i]) == 1:
		s.append(i)
		visited[i] = 1
		dist[i] = 0
pos = 0
while pos < N:
	u = s[pos]
	pos += 1
	for v in g[u]:
		if not visited[v]:
			visited[v] = 1
			s.append(v)
			dist[v] = dist[u] + 1
keys = [dist[u] + dist[v] for (u, v) in E]
X = [(e, n) for (n, e) in enumerate(sorted(range(N - 1), key=lambda x: keys[x]))]
print('\n'.join([str(i) for (_, i) in sorted(X)]))
print()


import sys
input = lambda : sys.stdin.readline().rstrip()
from collections import deque
n = int(input())
tree = [[] for i in range(n)]
s = []
for _ in range(n - 1):
	(a, b) = map(int, input().split())
	s.append([a - 1, b - 1])
	tree[a - 1].append(b - 1)
	tree[b - 1].append(a - 1)
ans = [-1] * (n - 1)
maxx = 0
ind = -1
for i in range(len(tree)):
	if len(tree[i]) > maxx:
		maxx = len(tree[i])
		ind = i
st = deque([int(i) for i in range(n - 1)])
for i in range(len(s)):
	if ind in s[i]:
		ans[i] = st.popleft()
for i in range(len(ans)):
	if ans[i] == -1:
		ans[i] = st.pop()
for i in range(len(ans)):
	print(ans[i])


from collections import defaultdict
import sys
input = sys.stdin.readline

class Graph:

	def __init__(self, v):
		self.graph = defaultdict(list)
		self.min = 0
		self.max = v - 2
		self.edgeAns = defaultdict(dict)

	def addEdge(self, u, v):
		self.graph[u].append(v)
		self.graph[v].append(u)

	def dfs(self, v):
		for i in range(1, v + 1):
			if len(self.graph[i]) > 2:
				for j in range(3):
					g.edgeAns[i][self.graph[i][j]] = j
					g.edgeAns[self.graph[i][j]][i] = j
				break

	def isLinear(self, n):
		cnt = 0
		for i in range(1, n + 1):
			if len(self.graph[i]) == 2:
				cnt += 1
		if cnt == n - 2:
			m = 0
			for i in range(1, n + 1):
				if len(self.graph[i]) == 1:
					self.edgeAns[i][self.graph[i][0]] = m
					self.edgeAns[i][self.graph[i][0]] = m
					m += 1
		else:
			self.dfs(n)
n = int(input())
g = Graph(n)
temp = []
for _ in range(n - 1):
	(a, b) = map(int, input().split())
	g.addEdge(a, b)
	temp.append((a, b))
g.isLinear(n)
max = n - 2
if n == 2:
	print(0)
else:
	for (i, j) in temp:
		if i in g.edgeAns[j]:
			print(g.edgeAns[j][i])
		else:
			print(max)
			max -= 1


import sys
input = sys.stdin.readline
n = int(input())
d = [0 for i in range(n)]
arr = []
for _ in range(n - 1):
	temp = [int(x) for x in input().split()]
	d[temp[0] - 1] += 1
	d[temp[1] - 1] += 1
	arr.append(temp)
maxi = d.index(max(d))
curr = 0
dusra = max(d)
ans = []
for i in range(n - 1):
	if arr[i][0] - 1 == maxi or arr[i][1] - 1 == maxi:
		ans.append(curr)
		curr += 1
	else:
		ans.append(dusra)
		dusra += 1
for i in ans:
	print(i)


n = int(input())
w = []
for j in range(n - 1):
	w.append([int(k) for k in input().split()])
q = {}
for j in w:
	if j[0] in q:
		q[j[0]].append(j[1])
	else:
		q[j[0]] = [j[1]]
	if j[1] in q:
		q[j[1]].append(j[0])
	else:
		q[j[1]] = [j[0]]
if n == 2:
	print(0)
else:
	eta = {}
	zeta = 0
	for j in q.keys():
		if len(q[j]) == 1:
			eta[j, q[j][0]] = zeta
			zeta += 1
	for j in w:
		if (j[0], j[1]) in eta:
			print(eta[j[0], j[1]])
		elif (j[1], j[0]) in eta:
			print(eta[j[1], j[0]])
		else:
			print(zeta)
			zeta += 1


import sys
input = lambda : sys.stdin.readline().rstrip()
n = int(input())
tree = [[] for i in range(n)]
s = []
for _ in range(n - 1):
	(a, b) = map(int, input().split())
	s.append([a - 1, b - 1])
	tree[a - 1].append(b - 1)
	tree[b - 1].append(a - 1)
ans = [-1] * (n - 1)
maxx = 0
ind = -1
for i in range(len(tree)):
	if len(tree[i]) > maxx:
		maxx = len(tree[i])
		ind = i
k = 0
st = set([int(i) for i in range(n - 1)])
for i in range(len(s)):
	if ind in s[i]:
		ans[i] = k
		st.remove(k)
		k += 1
st = list(st)
for i in range(len(ans)):
	if ans[i] == -1:
		ans[i] = st[-1]
		st.pop()
for i in range(len(ans)):
	print(ans[i])


n = int(input())
edges = [tuple(map(int, input().split())) for _ in range(n - 1)]
ans = {e: -1 for e in edges}
gs = [[] for _ in range(n + 1)]
for (u, v) in edges:
	gs[u].append(v)
	gs[v].append(u)
g = max(range(1, n + 1), key=lambda x: len(gs[x]))
cnt = 0
for v in gs[g]:
	uv = (g, v)
	if uv not in ans:
		uv = (v, g)
	ans[uv] = cnt
	cnt += 1
for a in ans.values():
	if a == -1:
		print(cnt)
		cnt += 1
	else:
		print(a)


n = int(input())
inputEdges = []
adjList = [[] for i in range(0, n + 1)]
for i in range(0, n - 1):
	edge = list(map(lambda x: int(x), input().split()))
	inputEdges.append(edge)
	adjList[edge[0]].append(edge[1])
	adjList[edge[1]].append(edge[0])
isLinear = True
junction = 0
for i in range(1, n + 1):
	if len(adjList[i]) >= 3:
		junction = i
		isLinear = False
		break
high = n - 2
low = 0
if isLinear:
	for i in range(0, n - 1):
		print(i)
else:
	for e in inputEdges:
		if e[0] == junction or e[1] == junction:
			print(low)
			low += 1
		else:
			print(high)
			high -= 1


n = int(input())
occ = [0 for i in range(n)]
graph = [[0, 0] for i in range(n - 1)]
for i in range(n - 1):
	(x, y) = map(int, input().split())
	occ[x - 1] += 1
	occ[y - 1] += 1
	graph[i][0] = x - 1
	graph[i][1] = y - 1
fin = [-1 for i in range(n - 1)]
for i in range(n):
	if occ[i] >= 3:
		var = 0
		for j in range(n - 1):
			if graph[j][0] == i or graph[j][1] == i:
				fin[j] = var
				var += 1
		break
else:
	var = 0
	for i in range(n):
		if var > 1:
			break
		if occ[i] == 1:
			for j in range(n - 1):
				if graph[j][0] == i or graph[j][1] == i:
					fin[j] = var
					var += 1
					break
for i in fin:
	if n == 2:
		print(0)
		break
	if i == -1:
		print(var)
		var += 1
	else:
		print(i)


lis = []
n = int(input())
dic = {}
approve = -1
for i in range(n - 1):
	(a, b) = map(int, input().split())
	lis.append([a, b])
	dic[a] = dic.get(a, 0) + 1
	dic[b] = dic.get(b, 0) + 1
	if dic[a] == 3 and approve == -1:
		approve = a
	if dic[b] == 3 and approve == -1:
		approve = b
start = 0
if approve != -1:
	start2 = dic[approve]
if approve == -1:
	for i in lis:
		print(start)
		start += 1
else:
	for i in lis:
		if i[0] == approve or i[1] == approve:
			print(start)
			start += 1
		else:
			print(start2)
			start2 += 1


n = int(input())
a = []
f = [0] * (n + 1)
for i in range(n - 1):
	fff = list(map(int, input().split()))
	fff.sort()
	a.append(fff)
	f[fff[0]] += 1
	f[fff[1]] += 1
ind = -1
mx = -1
for i in range(n):
	if f[i] > mx:
		mx = f[i]
		ind = i
i = 0
j = mx
ans = []
for k in a:
	if k[0] == ind or k[1] == ind:
		ans.append(i)
		i += 1
	else:
		ans.append(j)
		j += 1
for k in ans:
	print(k)


n = int(input())
freq = [0] * (n + 1)
adj = []
for i in range(n - 1):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	freq[a] += 1
	freq[b] += 1
	adj.append([a, b])
cnt = 0
mx = n - 2
for (a, b) in adj:
	if freq[a] == 1 or freq[b] == 1:
		print(cnt)
		cnt += 1
	else:
		print(mx)
		mx -= 1


n = int(input())
present = [0] * (n + 1)
l = []
for i in range(n - 1):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	present[a] += 1
	present[b] += 1
	l.append([a, b])
s = 0
m = n - 2
for (a, b) in l:
	if present[a] == 1 or present[b] == 1:
		print(s)
		s += 1
	else:
		print(m)
		m -= 1


import sys
input = sys.stdin.readline
sys.setrecursionlimit(10 ** 6)

def in_int():
	return int(input())

def in_list():
	return list(map(int, input().split()))

def in_str():
	s = input()
	return list(s[:len(s) - 1])

def in_ints():
	return map(int, input().split())
n = in_int()
g = [[] for i in range(n + 1)]
e = [-1] * (n - 1)
vv = 0
mx = 0
for xx in range(n - 1):
	(u, v) = in_ints()
	g[u].append((v, xx))
	if len(g[u]) > mx:
		mx = len(g[u])
		vv = u
	g[v].append((u, xx))
	if len(g[v]) > mx:
		mx = len(g[v])
		vv = v
count = 0
for (v, i) in g[vv]:
	if e[i] == -1:
		e[i] = count
		count += 1
for i in range(len(e)):
	if e[i] == -1:
		e[i] = count
		count += 1
	print(e[i])


import sys

def input():
	return sys.stdin.readline().strip()

def list2d(a, b, c):
	return [[c] * b for i in range(a)]

def list3d(a, b, c, d):
	return [[[d] * c for j in range(b)] for i in range(a)]

def list4d(a, b, c, d, e):
	return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]

def ceil(x, y=1):
	return int(-(-x // y))

def INT():
	return int(input())

def MAP():
	return map(int, input().split())

def LIST(N=None):
	return list(MAP()) if N is None else [INT() for i in range(N)]

def Yes():
	print('Yes')

def No():
	print('No')

def YES():
	print('YES')

def NO():
	print('NO')
INF = 10 ** 18
MOD = 10 ** 9 + 7
N = INT()
nodes = [[] for i in range(N)]
ptoi = {}
ans = [0] * (N - 1)
for i in range(N - 1):
	(a, b) = MAP()
	a -= 1
	b -= 1
	nodes[a].append(b)
	nodes[b].append(a)
	ptoi[min(a, b), max(a, b)] = i
leaves = []
for i in range(N):
	if len(nodes[i]) == 1:
		leaves.append(i)
		if len(leaves) == 3:
			break
ans = [0] * (N - 1)
if len(leaves) < 3:
	for i in range(N - 1):
		ans[i] = i
else:
	edges = set()
	for (i, u) in enumerate(leaves):
		v = nodes[u][0]
		idx = ptoi[min(u, v), max(u, v)]
		edges.add(idx)
		ans[idx] = i
	cnt = 3
	for i in range(N - 1):
		if i in edges:
			continue
		ans[i] = cnt
		cnt += 1
[print(a) for a in ans]


from collections import defaultdict
import sys, math
f = None
try:
	f = open('q1.input', 'r')
except IOError:
	f = sys.stdin
if 'xrange' in dir(__builtins__):
	range = xrange

def print_case_iterable(case_num, iterable):
	print('Case #{}: {}'.format(case_num, ' '.join(map(str, iterable))))

def print_case_number(case_num, iterable):
	print('Case #{}: {}'.format(case_num, iterable))

def print_iterable(A):
	print(' '.join(A))

def read_int():
	return int(f.readline().strip())

def read_int_array():
	return [int(x) for x in f.readline().strip().split(' ')]

def rns():
	a = [x for x in f.readline().split(' ')]
	return (int(a[0]), a[1].strip())

def read_string():
	return list(f.readline().strip())

def solution(A, n, d):
	leaves = [x for x in d if d[x] == 1]
	if len(leaves) == 2:
		return '\n'.join(map(str, range(n - 1)))
	s = ''
	cnt = 0
	other_cnt = 3
	si = set()
	for (x, y) in A:
		if (d[x] == 1 or d[y] == 1) and cnt < 3:
			si.add(cnt)
			s += str(cnt) + '\n'
			cnt += 1
		else:
			si.add(other_cnt)
			s += str(other_cnt) + '\n'
			other_cnt += 1
	return s

def main():
	T = 1
	for i in range(T):
		n = read_int()
		d = defaultdict(int)
		A = []
		for j in range(n - 1):
			A.append(read_int_array())
			d[A[-1][0]] += 1
			d[A[-1][1]] += 1
		x = solution(A, n, d)
		if 'xrange' not in dir(__builtins__):
			print(x)
		else:
			(print >> output, str(x))
	if 'xrange' in dir(__builtins__):
		print(output.getvalue())
		output.close()
if 'xrange' in dir(__builtins__):
	import cStringIO
	output = cStringIO.StringIO()
main()


n = int(input())
l = []
freq = [0] * (n + 1)
for _ in range(n - 1):
	l1 = list(map(int, input().split()))
	freq[l1[0]] += 1
	freq[l1[1]] += 1
	l.append(l1)
(s, e) = (0, n - 2)
ans = []
for l1 in l:
	if freq[l1[0]] == 1 or freq[l1[1]] == 1:
		ans.append(s)
		s += 1
	else:
		ans.append(e)
		e -= 1
for i in ans:
	print(i)


n = int(input())
G = [0] * n
V = []
for i in range(n - 1):
	(x, y) = [int(x) - 1 for x in input().split()]
	G[x] += 1
	G[y] += 1
	V.append((x, y))
good = -1
for i in range(n):
	if G[i] > 2:
		good = i
		break
if good == -1:
	for i in range(n - 1):
		print(i)
else:
	deg = G[good] - 1
	bad = 0
	for i in range(n - 1):
		if good in V[i]:
			print(deg)
			deg -= 1
		else:
			print(G[good] + bad)
			bad += 1


n = int(input())
d = {}
l = []
for i in range(n - 1):
	(a, b) = map(int, input().split())
	l.append([a, b])
	if a in d:
		d[a] += 1
	else:
		d[a] = 1
	if b in d:
		d[b] += 1
	else:
		d[b] = 1
ans = [-1] * (n - 1)
pew = 0
for i in range(1, n + 1):
	if d[i] >= 3:
		for j in range(n - 1):
			if l[j][0] == i or l[j][1] == i:
				ans[j] = pew
				pew += 1
				if pew == 3:
					break
		for j in range(n - 1):
			if ans[j] == -1:
				ans[j] = pew
				pew += 1
		break
for j in range(n - 1):
	if ans[j] == -1:
		ans[j] = pew
		pew += 1
for i in ans:
	print(i)


from collections import deque
El = []
Er = []
En = []
N = int(input())
g = [[] for _ in range(N + 1)]
dist = [2 ** 20 for _ in range(N + 1)]
visited = [0] * (N + 1)
s = deque([1])
for num in range(N - 1):
	(u, v) = list(map(int, input().split()))
	g[u].append(v)
	g[v].append(u)
	El.append(v)
	Er.append(u)
	En.append(num)
for i in range(1, N + 1):
	if len(g[i]) == 1:
		s.append(i)
		visited[i] = 1
		dist[i] = 0
while s:
	u = s.popleft()
	for v in g[u]:
		if not visited[v]:
			visited[v] = 1
			s.append(v)
			dist[v] = dist[u] + 1
keys = [dist[el] + dist[er] for (el, er) in zip(El, Er)]
X = [(e, n) for (n, e) in enumerate(sorted(En, key=lambda x: keys[x]))]
print('\n'.join([str(i) for (_, i) in sorted(X)]))


from collections import deque
q = deque()
p = 0
n = int(input())
color = [0 for i in range(n)]
mass = [[0] for i in range(n)]
for i in range(n - 1):
	(x, y) = map(int, input().split())
	mass[x - 1] += [[y - 1, i]]
	mass[y - 1] += [[x - 1, i]]
	mass[x - 1][0] += 1
	mass[y - 1][0] += 1
k = 0
m = []
f = 1
for i in range(n):
	if mass[i][0] == n - 1:
		for i in range(n - 1):
			print(i)
		exit()
	if mass[i][0] == 2:
		k += 1
	if mass[i][0] == 1:
		m += [mass[i][1][1]]
		if f == 1:
			p = i
		f = 0
if k == n - 2:
	for i in range(n - 1):
		print(i)
	exit()
if n == 2:
	print(0)
	print(1)
	exit()
res = [-1 for i in range(n - 1)]
if len(m) >= 3:
	res[m[0]] = 0
	res[m[1]] = 1
	res[m[2]] = 2
j = 3
for i in range(n - 1):
	if res[i] == -1:
		print(j)
		j += 1
	else:
		print(res[i])


import sys
input = sys.stdin.readline
n = int(input())
d = {}
dc = {}
for i in range(n - 1):
	(a, b) = map(int, input().split())
	dc[a, b] = -1
	if a not in d:
		d[a] = []
	if b not in d:
		d[b] = []
	d[a].append(b)
	d[b].append(a)
ct = 0
b = False
for i in d.keys():
	if len(d[i]) > 2:
		for j in d[i]:
			if (i, j) in dc and dc[i, j] == -1:
				dc[i, j] = ct
				ct += 1
			elif (j, i) in dc and dc[j, i] == -1:
				dc[j, i] = ct
				ct += 1
			b = True
			if ct == 3:
				break
	if b == True:
		break
if b == True:
	val = 3
	for i in dc.keys():
		if dc[i] == -1:
			dc[i] = val
			val += 1
	for i in dc.keys():
		print(dc[i])
else:
	lt = []
	for i in d.keys():
		if len(d[i]) == 1:
			lt.append(i)
	a = lt[0]
	b = lt[1]
	if (a, d[a][0]) in dc:
		dc[a, d[a][0]] = 0
	else:
		dc[d[a][0], a] = 0
	if (b, d[b][0]) in dc:
		dc[b, d[b][0]] = 1
	else:
		dc[d[b][0], b] = 1
	val = 2
	for i in dc.keys():
		if dc[i] == -1:
			dc[i] = val
			val += 1
	if n == 2:
		print('0')
	else:
		for i in dc.keys():
			print(dc[i])


from operator import itemgetter, attrgetter, methodcaller
n = int(input())
d = dict()
a = list()
for i in range(n - 1):
	(u, v) = map(int, input().split())
	a.append([u, v, i])
	if u in d.keys():
		d[u] += 1
	else:
		d[u] = 1
	if v in d.keys():
		d[v] += 1
	else:
		d[v] = 1
b = list()
for i in range(n - 1):
	b.append(-1)
	a[i].append(min(d[a[i][0]], d[a[i][1]]))
a.sort(key=itemgetter(3))
c = 0
for i in range(n - 1):
	b[a[i][2]] = c
	c += 1
for i in range(n - 1):
	print(b[i])


def read_int():
	return int(input().strip())

def read_ints():
	return list(map(int, input().strip().split(' ')))

def solve():
	N = read_int()
	counts = [0] * N
	edges = []
	for _ in range(N - 1):
		edge = read_ints()
		edge[0] -= 1
		edge[1] -= 1
		edges.append(edge)
		counts[edge[0]] += 1
		counts[edge[1]] += 1
	C = 0
	labels = [-1] * (N - 1)
	for (i, (u, v)) in enumerate(edges):
		if counts[u] == 1 or counts[v] == 1:
			labels[i] = C
			C += 1
	for i in range(N - 1):
		if labels[i] == -1:
			labels[i] = C
			C += 1
	for label in labels:
		print(label)
solve()


from collections import defaultdict, deque
from itertools import permutations
from sys import stdin, stdout
from bisect import bisect_left, bisect_right
from copy import deepcopy
import heapq
int_input = lambda : int(stdin.readline())
string_input = lambda : stdin.readline().split()
multi_int_input = lambda : map(int, stdin.readline().split())
multi_input = lambda : stdin.readline().split()
list_input = lambda : list(map(int, stdin.readline().split()))
string_list_input = lambda : list(string_input())
MOD = pow(10, 9) + 7
n = int_input()
mini = 0
graph = []
for i in range(n + 5):
	graph.append([])
inputorder = []
ans = []
frequency = {}
if n == 2:
	(u, v) = multi_int_input()
	print(0)
elif n == 3:
	(a, b) = multi_int_input()
	(b, c) = multi_int_input()
	print(0)
	print(1)
else:
	count = 0
	for _ in range(n - 1):
		(u, v) = multi_int_input()
		inputorder.append([u, v])
		graph[u].append(v)
		graph[v].append(u)
	threeDegreePoint = -1
	for i in range(1, n + 1):
		if len(graph[i]) >= 3:
			threeDegreePoint = i
	if threeDegreePoint == -1:
		for i in range(0, n - 1):
			print(i)
	else:
		a = 0
		b = 3
		count = 0
		for x in inputorder:
			if (x[0] == threeDegreePoint or x[1] == threeDegreePoint) and count < 3:
				print(a)
				count += 1
				a += 1
			else:
				print(b)
				b += 1


import sys
input = sys.stdin.readline
from math import *
n = int(input())
a = [[] for i in range(n + 1)]
b = []
g = []
for i in range(n - 1):
	(x, y) = map(int, input().split())
	a[x].append(y)
	a[y].append(x)
	b.append([x, y])
for i in range(1, n + 1):
	g.append([len(a[i]), i, a[i]])
g.sort(reverse=True)
s = {}
r = 0
for i in range(0, n):
	for j in g[i][2]:
		m1 = min(g[i][1], j)
		m2 = max(g[i][1], j)
		h = str(m1) + '*' + str(m2)
		if h in s:
			continue
		s[h] = r
		r += 1
for i in range(len(b)):
	m1 = min(b[i])
	m2 = max(b[i])
	h = str(m1) + '*' + str(m2)
	if h in s:
		print(s[str(m1) + '*' + str(m2)])


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
n = int(input())
graph = [[] for i in range(n + 1)]
di = {}
for i in range(n - 1):
	(x, y) = map(int, input().split())
	graph[x] += [y]
	graph[y] += [x]
	di[str(x) + ',' + str(y)] = i
	di[str(y) + ',' + str(x)] = i
count = 0
ans = [-1] * (n - 1)
for i in range(1, n + 1):
	if len(graph[i]) > 2:
		for j in graph[i]:
			k = di[str(i) + ',' + str(j)]
			ans[k] = count
			count += 1
		break
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = count
		count += 1
print('\n'.join((str(k) for k in ans)))


import sys
input = sys.stdin.readline
n = int(input())
l = [[] for i in range(n)]
ans = {}
initial = []
for i in range(n - 1):
	(a, b) = list(map(int, input().split()))
	initial.append((a - 1, b - 1))
	ans[a - 1, b - 1] = -1
	ans[b - 1, a - 1] = -1
	l[a - 1].append(b - 1)
	l[b - 1].append(a - 1)
flag = 0
for i in range(len(l)):
	if len(l[i]) > 2:
		flag = 1
		index = i
		break
if flag == 0:
	for i in range(n - 1):
		print(i)
else:
	for i in range(3):
		ans[index, l[index][i]] = i
		ans[l[index][i], index] = i
	k = 3
	for i in range(n - 1):
		if ans[initial[i][0], initial[i][1]] == -1:
			print(k)
			k += 1
		else:
			print(ans[initial[i][0], initial[i][1]])


from sys import stdin, stdout

def II():
	return int(stdin.readline())

def MI():
	return map(int, stdin.readline().split())
n = II()
deg = [0] * n
g = []
for _ in range(n - 1):
	(u, v) = MI()
	(u, v) = (u - 1, v - 1)
	deg[u] += 1
	deg[v] += 1
	g.append((u, v))
(s, e) = (0, n - 2)
for (x, y) in g:
	if deg[x] == 1 or deg[y] == 1:
		stdout.write(str(s) + '\n')
		s += 1
	else:
		stdout.write(str(e) + '\n')
		e -= 1


import sys
import math
from collections import Counter

def IO():
	sys.stdin = open('pyinput.txt', 'r')
	sys.stdout = open('pyoutput.txt', 'w')

def GCD(a, b):
	if b == 0:
		return a
	else:
		return GCD(b, a % b)

def LCM(a, b):
	return a * (b // GCD(a, b))

def scan(TYPE_1, TYPE_2=0):
	if TYPE_1 == int:
		return map(int, sys.stdin.readline().strip().split())
	elif TYPE_1 == float:
		return map(float, sys.stdin.readline().strip().split())
	elif TYPE_1 == list and TYPE_2 == float:
		return list(map(float, sys.stdin.readline().strip().split()))
	elif TYPE_1 == list and TYPE_2 == int:
		return list(map(int, sys.stdin.readline().strip().split()))
	elif TYPE_1 == str:
		return sys.stdin.readline().strip()
	else:
		print('ERROR!!!!')

def main():
	n = int(input())
	a = [[] for i in range(n + 3)]
	mp = {}
	for i in range(n - 1):
		(u, v) = scan(int)
		(a[u].append(v), a[v].append(u))
		mp[u, v] = -1
	mx = -1
	idx = 0
	for i in range(1, n + 1):
		if len(a[i]) > mx:
			mx = len(a[i])
			idx = i
	cnt1 = 0
	cnt2 = n - 2
	for (a, b) in mp:
		if a == idx or b == idx:
			print(cnt1)
			cnt1 += 1
		else:
			print(cnt2)
			cnt2 -= 1
main()


import os, sys, bisect, copy
from collections import defaultdict, Counter, deque
from functools import lru_cache
if os.path.exists('in.txt'):
	sys.stdin = open('in.txt', 'r')
if os.path.exists('out.txt'):
	sys.stdout = open('out.txt', 'w')

def input():
	return sys.stdin.readline()

def mapi(arg=0):
	return map(int if arg == 0 else str, input().split())
n = int(input())
gr = defaultdict(list)
x = 0
level = {}
path = {}
ans = [0] * (2 * n)
for i in range(n - 1):
	(u, v) = mapi()
	gr[u].append([v, i])
	gr[v].append([u, i])
flag = True
for i in range(1, n):
	if len(gr[i]) > 2:
		flag = False
if flag:
	for i in range(n - 1):
		print(i)
else:
	cent = -1
	for i in range(1, n + 1):
		if len(gr[i]) > 2:
			cent = i
			break
	cnt = 1
	for i in gr[cent]:
		idx = i[1]
		ans[idx] = cnt
		cnt += 1
	for i in range(n - 1):
		if ans[i] == 0:
			ans[i] = cnt
			cnt += 1
	for i in range(n - 1):
		print(ans[i] - 1)


import math
import sys
from collections import defaultdict, Counter, deque, OrderedDict
import bisect
input = iter(sys.stdin.buffer.read().decode().splitlines()).__next__
ilele = lambda : map(int, input().split())
alele = lambda : list(map(int, input().split()))

def list2d(a, b, c):
	return [[c] * b for i in range(a)]
from itertools import accumulate, groupby
import sys
mod = 1000000007
graph = []

def addEdge(a, b):
	graph[a].append(b)
	graph[b].append(a)
N = int(input())
graph = defaultdict(list)
G = []
for i in range(N - 1):
	(u, v) = ilele()
	addEdge(u, v)
	G.append((u, v))
Ans = {}
maxi = 0
a = 0
for (i, j) in graph.items():
	if len(j) > maxi:
		maxi = len(j)
		a = i
k = 0
for i in graph[a]:
	Ans[i, a] = k
	Ans[a, i] = k
	k += 1
for i in G:
	x = Ans.get(i, -1)
	if x != -1:
		print(x)
	else:
		print(k)
		k += 1


class Graph:

	def __init__(self, vertices):
		self.no_of_vertices = vertices
		self.graph = dict()
		for i in range(1, self.no_of_vertices + 1):
			self.graph[i] = []

	def add_edge(self, u, v):
		self.graph[u].append(v)
		self.graph[v].append(u)
n = int(input())
g = Graph(n)
edges = []
for _ in range(n - 1):
	[l, r] = [int(i) for i in input().split()]
	edges.append((l, r))
for (u, v) in edges:
	g.add_edge(u, v)
labels = [None] * (n - 1)
for u in g.graph:
	if len(g.graph[u]) > 2:
		break
l = 0
for i in range(n - 1):
	if u in edges[i]:
		labels[i] = l
		l = l + 1
for i in range(n - 1):
	if labels[i] == None:
		labels[i] = l
		l = l + 1
for i in labels:
	print(i)


import math
from collections import defaultdict
n = int(input())
adj_lis = defaultdict(int)
edges = []
for i in range(n - 1):
	(x, y) = [int(i) for i in input().split()]
	adj_lis[x] += 1
	adj_lis[y] += 1
	edges.append([x, y])
leaves = {}
for i in range(1, n + 1):
	if adj_lis[i] == 1:
		leaves[i] = 1
tot_leaves = len(list(leaves.keys()))
high = tot_leaves
low = 0
for i in range(len(edges)):
	(x, y) = edges[i]
	if x in leaves or y in leaves:
		print(low)
		low += 1
	else:
		print(high)
		high += 1


def Solution():
	n = int(input())
	c = {}
	edges = []
	(f, l) = (0, n - 2)
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		edges.append((u, v))
		c.setdefault(u, 0)
		c.setdefault(v, 0)
		c[u] += 1
		c[v] += 1
	for i in edges:
		if c[i[0]] == 1 or c[i[1]] == 1:
			print(f)
			f += 1
		else:
			print(l)
			l -= 1
Solution()


n = int(input())
A = []
B = [0] * (n - 1)
G = [[] for i in range(n)]
GG = [[0] * 2 for i in range(n - 1)]
for i in range(n - 1):
	(a, b) = map(int, input().split())
	c = a
	a = min(b, c)
	b = max(b, c)
	GG[i] = [a, b]
	G[a - 1].append(b - 1)
	G[b - 1].append(a - 1)
	A.append(a * 10 ** 6 + b)
D = dict(zip(A, B))
a = 10 ** 6
b = 10 ** 6
c = 10 ** 6
for i in range(n):
	if len(G[i]) >= 3:
		a = i
		break
if a == 10 ** 6:
	for i in range(n - 1):
		print(i)
else:
	B = []
	for i in range(3):
		D[min(a + 1, G[a][i] + 1) * 10 ** 6 + max(a + 1, G[a][i] + 1)] = i
		B.append(min(a + 1, G[a][i] + 1) * 10 ** 6 + max(a + 1, G[a][i] + 1))
	f = 3
	x = 3
	for i in range(n - 1):
		if GG[i][0] * 10 ** 6 + GG[i][1] not in B:
			print(x)
			x = x + 1
		else:
			print(D[GG[i][0] * 10 ** 6 + GG[i][1]])


import sys, os, io

def rs():
	return sys.stdin.readline().rstrip()

def ri():
	return int(sys.stdin.readline())

def ria():
	return list(map(int, sys.stdin.readline().split()))

def ws(s):
	sys.stdout.write(s + '\n')

def wi(n):
	sys.stdout.write(str(n) + '\n')

def wia(a):
	sys.stdout.write(' '.join([str(x) for x in a]) + '\n')
import math, datetime, functools, itertools, operator, bisect, fractions, statistics
from collections import deque, defaultdict, OrderedDict, Counter
from fractions import Fraction
from decimal import Decimal
from sys import stdout
from heapq import heappush, heappop, heapify, _heapify_max, _heappop_max, nsmallest, nlargest
INF = 99999999999999999999999999999999

def main():
	mod = 1000000007
	starttime = datetime.datetime.now()
	if os.path.exists('input.txt'):
		sys.stdin = open('input.txt', 'r')
		sys.stdout = open('output.txt', 'w')
	tc = 1
	for _ in range(tc):
		n = ri()
		graph = [[] for i in range(n + 1)]
		indegrees = [0] * (n + 1)
		m = 0
		z = []
		for i in range(n - 1):
			(a, b) = ria()
			z.append([a, b])
			graph[a].append(b)
			graph[b].append(a)
			indegrees[a] += 1
			indegrees[b] += 1
			m = max(indegrees[a], indegrees[b], m)
		if m < 3:
			for i in range(n - 1):
				wi(i)
		else:
			for i in range(n + 1):
				if indegrees[i] == m:
					node = i
					break
			count1 = n - 2
			count2 = 2
			for (x, y) in z:
				if count2 >= 0 and (x == node or y == node):
					print(count2)
					count2 -= 1
				else:
					print(count1)
					count1 -= 1
	endtime = datetime.datetime.now()
	time = (endtime - starttime).total_seconds() * 1000
	if os.path.exists('input.txt'):
		print('Time:', time, 'ms')

class FastReader(io.IOBase):
	newlines = 0

	def __init__(self, fd, chunk_size=1024 * 8):
		self._fd = fd
		self._chunk_size = chunk_size
		self.buffer = io.BytesIO()

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, self._chunk_size))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self, size=-1):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, self._chunk_size if size == -1 else size))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

class FastWriter(io.IOBase):

	def __init__(self, fd):
		self._fd = fd
		self.buffer = io.BytesIO()
		self.write = self.buffer.write

	def flush(self):
		os.write(self._fd, self.buffer.getvalue())
		(self.buffer.truncate(0), self.buffer.seek(0))

class FastStdin(io.IOBase):

	def __init__(self, fd=0):
		self.buffer = FastReader(fd)
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

class FastStdout(io.IOBase):

	def __init__(self, fd=1):
		self.buffer = FastWriter(fd)
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.flush = self.buffer.flush
sys.stdin = FastStdin()
sys.stdout = FastStdout()
main()


dic = {}
check = []
size = int(input())
for _ in range(size - 1):
	(a, b) = map(int, input().split())
	check.append((a, b))
	if a not in dic.keys():
		dic.update({a: 1})
	else:
		dic[a] += 1
	if b not in dic.keys():
		dic.update({b: 1})
	else:
		dic[b] += 1
(crat, trap) = (0, size - 2)
for (j, k) in check:
	if dic[j] == 1 or dic[k] == 1:
		print(crat)
		crat += 1
	else:
		print(trap)
		trap -= 1


import sys
import collections
input = sys.stdin.readline

def main():
	N = int(input())
	AB = [[int(x) for x in input().split()] for _ in range(N - 1)]
	V = [[] for j in range(N)]
	for (i, (a, b)) in enumerate(AB):
		V[a - 1].append([b - 1, i])
		V[b - 1].append([a - 1, i])
	f = False
	ans = [-1] * (N - 1)
	for v in V:
		if len(v) >= 3:
			f = True
			for i in range(3):
				ans[v[i][1]] = i
			break
	cnt = 0
	if f:
		cnt = 3
	for a in ans:
		if a == -1:
			print(cnt)
			cnt += 1
		else:
			print(a)
main()


n = int(input())
adj = [[] for _ in range(n + 1)]
visited = [False] * (n + 1)
edge_to_ind = dict()
ans = [-1] * (n + 1)
for i in range(n - 1):
	(u, v) = map(int, input().split())
	if u > v:
		(u, v) = (v, u)
	edge_to_ind[u, v] = i
	adj[u].append(v)
	adj[v].append(u)
for i in range(1, n + 1):
	if len(adj[i]) > len(adj[u]):
		u = i
num = 0
for v in adj[u]:
	if (u, v) in edge_to_ind:
		ans[edge_to_ind[u, v]] = num
		num += 1
	elif (v, u) in edge_to_ind:
		ans[edge_to_ind[v, u]] = num
		num += 1
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = num
		num += 1
for i in range(n - 1):
	print(ans[i])


import sys
from sys import stdin, stdout
adj = [[] for i in range(10 ** 5 + 7)]
n = int(input())
query = []
for i in range(n - 1):
	(u, v) = map(int, input().split())
	query.append([u, v])
	adj[u].append(v)
	adj[v].append(u)
flag = True
vertex = -1
for i in range(n + 1):
	if len(adj[i]) >= 3:
		flag = False
		vertex = i
if flag:
	for i in range(n - 1):
		stdout.write(str(i) + '\n')
	sys.exit()
color = [adj[vertex][0], adj[vertex][1], adj[vertex][2]]
cnt = 3
for i in range(n - 1):
	if query[i][0] == vertex and query[i][1] in color:
		stdout.write(str(color.index(query[i][1])) + '\n')
	elif query[i][1] == vertex and query[i][0] in color:
		stdout.write(str(color.index(query[i][0])) + '\n')
	else:
		stdout.write(str(cnt) + '\n')
		cnt += 1


from math import *

def binarySearch(arr, x, i):
	l = i
	r = len(arr) - 1
	while l <= r:
		mid = (l + r) // 2
		if arr[mid] == x:
			return mid
		elif arr[mid] < x:
			l = mid + 1
		else:
			r = mid - 1
	return -1

def js(arr, x):
	l = 0
	r = len(arr) - 1
	ans = -1
	while l <= r:
		m = (l + r) // 2
		if arr[m] <= x:
			ans = m
			l = m + 1
		else:
			r = m - 1
	return ans

def jg(arr, x, i):
	l = i
	r = len(arr) - 1
	ans = -1
	while l <= r:
		m = (l + r) // 2
		if arr[m] >= x:
			ans = m
			r = m - 1
		else:
			l = m + 1
	return ans
n = int(input())
d = [0] * n
ans = [-1] * (n - 1)
q = []
for i in range(n - 1):
	(x, y) = map(int, input().split())
	q.append([x - 1, y - 1])
	d[x - 1] += 1
	d[y - 1] += 1
c = 0
for i in range(n - 1):
	if d[q[i][0]] == 1:
		ans[i] = c
		c += 1
	elif d[q[i][1]] == 1:
		ans[i] = c
		c += 1
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = c
		c += 1
for i in range(n - 1):
	print(ans[i])


n = int(input())
deg = [0] * n
neigh = [0] * n
for i in range(n - 1):
	(u, v) = map(int, input().split())
	deg[u - 1] += 1
	deg[v - 1] += 1
	neigh[u - 1] = i
	neigh[v - 1] = i
if n == 2:
	print(0)
elif max(deg) == 2:
	for i in range(n - 1):
		print(i)
else:
	p = [-1] * (n - 1)
	s = 0
	for i in range(n):
		if deg[i] == 1:
			p[neigh[i]] = s
			s += 1
	for i in range(n - 1):
		if p[i] == -1:
			p[i] = s
			s += 1
	for i in range(n - 1):
		print(p[i])


from sys import stdin
input = stdin.readline
n = int(input())
d = [0] * n
uv = []
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	u -= 1
	v -= 1
	d[u] += 1
	d[v] += 1
	uv.append((u, v))
i = j = -1
for (i, j) in enumerate(d):
	if j >= 3:
		break
c1 = 0
c2 = n - 2
for (u, v) in uv:
	if u == i or v == i:
		print(c1)
		c1 += 1
	else:
		print(c2)
		c2 -= 1


from sys import stdin, stdout
import sys
from bisect import bisect_left, bisect_right
import heapq
from collections import Counter
n = int(stdin.readline().strip())
adj = [[] for i in range(n)]
for i in range(n - 1):
	(u, v) = stdin.readline().strip().split(' ')
	(u, v) = (int(u), int(v))
	u -= 1
	v -= 1
	adj[u].append((v, i))
	adj[v].append((u, i))
ctr = 0
ans = [-1 for i in range(n - 1)]
adj = sorted(adj, key=lambda x: len(x), reverse=True)
for i in adj:
	for j in i:
		if ans[j[1]] == -1:
			ans[j[1]] = ctr
			ctr += 1
for i in ans:
	stdout.write(str(i) + '\n')


import sys
import bisect
from math import ceil, floor, factorial

def c(a, b):
	return int(factorial(a) / (factorial(b) * factorial(a - b)))
RI = lambda : [int(x) for x in sys.stdin.readline().split()]
ri = lambda : sys.stdin.readline().strip()
mod = 10 ** 9 + 7
n = int(ri())
ans = [0] * (n - 1)
lis = [[] for i in range(n)]
index = [[] for i in range(n)]
for _ in range(n - 1):
	(a, b) = RI()
	a -= 1
	b -= 1
	lis[a].append(b)
	lis[b].append(a)
	index[b].append(_)
	index[a].append(_)
pos = -1
for i in range(len(lis)):
	if len(lis[i]) >= 3:
		pos = i
		break
flag = [-1] * (n - 1)
ite = 1
if pos != -1:
	for i in range(len(index[pos])):
		ans[index[pos][i]] = ite
		flag[index[pos][i]] = 1
		ite += 1
	for i in range(n):
		if pos != i:
			for j in range(len(lis[i])):
				if flag[index[i][j]] == -1:
					ans[index[i][j]] = ite
					ite += 1
					flag[index[i][j]] = 1
else:
	for i in range(n):
		for j in range(len(lis[i])):
			if flag[index[i][j]] == -1:
				ans[index[i][j]] = ite
				ite += 1
				flag[index[i][j]] = 1
for i in range(len(ans)):
	print(ans[i] - 1)


import sys

def read_line():
	return sys.stdin.readline()[:-1]

def read_int():
	return int(sys.stdin.readline())

def read_int_line():
	return [int(v) for v in sys.stdin.readline().split()]
n = read_int()
d = {}
adj = {}
for i in range(n - 1):
	(u, v) = read_int_line()
	adj[u, v] = -1
	if u not in d:
		d[u] = 1
	else:
		d[u] += 1
	if v not in d:
		d[v] = 1
	else:
		d[v] += 1
vertex = -1
for i in adj:
	if vertex != -1:
		break
	if d[i[0]] >= 3:
		vertex = i[0]
	if d[i[1]] >= 3:
		vertex = i[1]
if vertex == -1:
	for i in range(n - 1):
		print(i)
else:
	c = 0
	for i in adj:
		if c < 3:
			if vertex in i:
				adj[i] = c
				c += 1
	l = list(adj.values())
	v = [i for i in range(3, n)]
	i = 0
	j = 0
	while i < n - 1 and j < n - 1:
		if l[i] != -1:
			print(l[i])
		else:
			print(v[j])
			j += 1
		i += 1


node_dict = {}
flag = True
mat = []
target = -1
n = int(input())
for t in range(n - 1):
	(u, v) = map(int, input().split())
	mat.append((u, v))
	if flag:
		try:
			node_dict[u] += 1
			if node_dict[u] == 3:
				target = u
				flag = False
		except KeyError:
			node_dict[u] = 1
		try:
			node_dict[v] += 1
			if node_dict[v] == 3:
				target = v
				flag = False
		except KeyError:
			node_dict[v] = 1
edges = n - 2
count = 0
for (u, v) in mat:
	if u == target or v == target:
		print(count)
		count += 1
	else:
		print(edges)
		edges -= 1


from sys import stdin
try:
	n = int(stdin.readline().rstrip())
	l = [0] * (n + 1)
	arr = []
	for _ in range(n - 1):
		(u, v) = map(int, stdin.readline().rstrip().split())
		arr.append((u, v))
		l[u] += 1
		l[v] += 1
	(x, y) = (0, n - 2)
	for (u, v) in arr:
		if l[u] == 1 or l[v] == 1:
			print(x)
			x += 1
		else:
			print(y)
			y -= 1
except:
	pass


n = int(input())
edges = [[] for i in range(0, n)]
for i in range(0, n - 1):
	(u, v) = map(int, input().split())
	edges[u - 1].append((v - 1, i))
	edges[v - 1].append((u - 1, i))
ans = [-1] * (n - 1)
cc = 0
for i in range(0, n):
	if len(edges[i]) == 1 and ans[edges[i][0][1]] == -1:
		ans[edges[i][0][1]] = cc
		cc += 1
for i in range(0, n - 1):
	if ans[i] == -1:
		ans[i] = cc
		cc += 1
for i in ans:
	print(i)


def f():
	n = int(input())
	neibors = [[] for i in range(n + 1)]
	orders = dict()
	for i in range(n - 1):
		(u, v) = [int(s) for s in input().split()]
		neibors[u].append(v)
		neibors[v].append(u)
		orders[u, v] = i
	leaves = []
	for i in range(1, n + 1):
		if len(neibors[i]) == 1:
			leaves.append(i)
	if len(leaves) <= 2:
		for i in range(n - 1):
			print(i)
		return
	ans = [-1] * (n - 1)
	for i in range(3):
		u = leaves[i]
		v = neibors[u][0]
		if (u, v) in orders:
			ans[orders[u, v]] = i
		else:
			ans[orders[v, u]] = i
	i = 3
	for j in range(n - 1):
		if ans[j] >= 0:
			continue
		ans[j] = i
		i += 1
	for a in ans:
		print(a)
f()


n = int(input())
l = []
m = [0] * (n + 1)
chk = [0] * (n + 1)
for _ in range(n - 1):
	(a, b) = map(int, input().split())
	if a > b:
		(a, b) = (b, a)
	m[a] += 1
	m[b] += 1
	l.append([a, b, -1])
if n == 2:
	print(0)
else:
	for x in range(1, n + 1):
		if m[x] == 1:
			chk[x] = 1
	cnt = 0
	cnt2 = n - 2
	for x in range(n - 1):
		if chk[l[x][0]] == 1 or chk[l[x][1]] == 1:
			l[x][2] = cnt
			cnt += 1
		else:
			l[x][2] = cnt2
			cnt2 -= 1
	for x in l:
		print(x[2])


from sys import stdin, stdout
import math, sys, heapq
from itertools import permutations, combinations
from collections import defaultdict, deque, OrderedDict
from os import path
import random
import bisect as bi

def yes():
	print('YES')

def no():
	print('NO')
if path.exists('input.txt'):
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')

	def I():
		return int(input())

	def In():
		return map(int, input().split())
else:

	def I():
		return int(stdin.readline())

	def In():
		return map(int, stdin.readline().split())

def dict(a):
	d = {}
	for x in a:
		if d.get(x, -1) != -1:
			d[x] += 1
		else:
			d[x] = 1
	return d

def find_gt(a, x):
	i = bi.bisect_left(a, x)
	if i != len(a):
		return i
	else:
		return -1

def main():
	try:
		n = I()
		d = defaultdict(list)
		ans = -1
		d1 = {}
		l = []
		for x in range(n - 1):
			(a, b) = In()
			d[a].append(b)
			d[b].append(a)
			temp = (min(a, b), max(a, b))
			l.append(temp)
			d1[temp] = -1
			if len(d[a]) >= 3:
				ans = a
			elif len(d[b]) >= 3:
				ans = b
		if ans == -1:
			for i in range(n - 1):
				print(i)
		else:
			i = 0
			for x in d[ans]:
				temp = (min(x, ans), max(x, ans))
				d1[temp] = i
				i += 1
			for j in l:
				if d1[j] == -1:
					d1[j] = i
					i += 1
			for x in l:
				print(d1[x])
	except:
		pass
M = 998244353
P = 1000000007
for _ in range(1):
	main()


n = int(input())
a = [[] for i in range(n + 1)]
ind = 0
d = {}
h = {}
import sys
for _ in range(n - 1):
	(x, y) = map(int, sys.stdin.readline().split())
	d[min(x, y), max(x, y)] = -1
	h[min(x, y), max(x, y)] = _
	a[x].append(y)
	a[y].append(x)
	if len(a[x]) > 2:
		ind = x
	if len(a[y]) > 2:
		ind = y
vis = [0] * (n + 1)
ans = [i for i in range(n - 1)]
if ind != 0:
	c = 0
	for j in a[ind]:
		d[min(j, ind), max(j, ind)] = c
		c += 1
	for j in d:
		if d[j] == -1:
			ans[h[j]] = c
			c += 1
		else:
			ans[h[j]] = d[j]
for i in ans:
	print(i)


n = int(input())
ans = [-1] * (n - 1)
d = dict()
for i in range(1, n + 1):
	d[i] = dict()
for i in range(n - 1):
	(u, v) = map(int, input().split())
	d[u][v] = i
	d[v][u] = i
cnt = 0
for i in range(1, n + 1):
	if len(d[i]) >= 3:
		for j in d[i].values():
			ans[j] = cnt
			cnt += 1
		break
for i in range(len(ans)):
	if ans[i] == -1:
		ans[i] = cnt
		cnt += 1
	print(ans[i])


n = int(input())
graph = [0] * (n + 1)
li = []
val = [-1] * (n - 1)
for _ in range(n - 1):
	(x, y) = map(int, input().strip().split(' '))
	li.append([x, y])
	graph[x] += 1
	graph[y] += 1
count = 0
for i in range(n - 1):
	if graph[li[i][0]] == 1 or graph[li[i][1]] == 1:
		val[i] = count
		count += 1
for i in val:
	if i == -1:
		print(count)
		count += 1
	else:
		print(i)


import sys
input = iter(sys.stdin.readlines()).__next__
import collections
n = int(input())
edges = collections.defaultdict(set)
e_labels = [None] * (n - 1)
for i in range(n - 1):
	(u, v) = map(int, input().split())
	edges[u].add(i)
	edges[v].add(i)
	if len(edges[v]) == 3:
		u = v
	if len(edges[u]) == 3:
		for (k, j) in enumerate(edges[u]):
			e_labels[j] = k
		k = 3
		for j in range(n - 1):
			if e_labels[j] == None:
				e_labels[j] = k
				k += 1
		break
else:
	e_labels = list(range(n - 1))
print(*e_labels, sep='\n')


n = int(input())
tree = [[] for _ in range(n + 1)]
enum = dict()
for i in range(n - 1):
	(u, v) = map(int, input().split())
	tree[u].append(v)
	tree[v].append(u)
	enum[u, v] = enum[v, u] = i
found = False
ans = list(range(n - 1))
free = set(range(n - 1))
for start in range(1, n + 1):
	if len(tree[start]) > 2:
		fork = tree[start][:3]
		found = True
		ans[enum[start, fork[2]]] = 0
		ans[enum[start, fork[0]]] = 1
		ans[enum[start, fork[1]]] = 2
		free.remove(enum[start, fork[2]])
		free.remove(enum[start, fork[0]])
		free.remove(enum[start, fork[1]])
		break
if found:
	for (i, w) in zip(free, range(3, n - 1)):
		ans[i] = w
print(*ans, sep='\n')


from sys import stdin
dic = {}
check = []
size = int(input())
for l in stdin.readlines():
	(a, b) = map(int, l.split())
	check.append((a, b))
	if a not in dic.keys():
		dic.update({a: 1})
	else:
		dic[a] += 1
	if b not in dic.keys():
		dic.update({b: 1})
	else:
		dic[b] += 1
(crat, trap) = (0, size - 2)
for (j, k) in check:
	if dic[j] == 1 or dic[k] == 1:
		print(crat)
		crat += 1
	else:
		print(trap)
		trap -= 1


I = lambda : map(int, input().split())
n = int(input())
l = [-1] * (n - 1)
g = [0] * (10 ** 5 + 2)
x = []
d = {}
for _ in range(n - 1):
	(a, b) = I()
	d[a] = d.get(a, 0) + 1
	d[b] = d.get(b, 0) + 1
	x.append([a, b])
for i in d.keys():
	if d[i] == 1:
		g[i] = 1
k = 0
for i in range(n - 1):
	if g[x[i][0]] or g[x[i][1]]:
		l[i] = k
		k += 1
for i in range(n - 1):
	if l[i] == -1:
		l[i] = k
		k += 1
print(*l)


import math, sys
q = 1
n = int(sys.stdin.readline())
lines = sys.stdin.readlines()
for _ in range(q):
	count = [0] * 100005
	arr = []
	for line in lines:
		(a, b) = map(int, line.split())
		count[a] += 1
		count[b] += 1
		arr.append([a, b])
	ans = []
	u = 0
	v = n - 2
	for i in range(len(arr)):
		if count[arr[i][0]] == 1 or count[arr[i][1]] == 1:
			ans.append(u)
			u += 1
		else:
			ans.append(v)
			v -= 1
	print('\n'.join(list(map(str, ans))))


n = int(input())
l = [0 for i in range(n + 1)]
deg3 = -1
edges = []
for i in range(n - 1):
	(u, v) = map(int, input().split())
	edges.append([u, v])
	l[u] += 1
	l[v] += 1
	if deg3 == -1:
		if l[u] == 3:
			deg3 = u
		if l[v] == 3:
			deg3 = v
if deg3 != -1:
	nC = 3
	deg3C = 0
	for i in edges:
		(u, v) = i
		if (u == deg3 or v == deg3) and deg3C != 3:
			print(deg3C)
			deg3C += 1
		else:
			print(nC)
			nC += 1
else:
	nC = 0
	for i in edges:
		print(nC)
		nC += 1


n = int(input())
x = [0] * n
a = []
for i in range(n - 1):
	(u, v) = map(int, input().split())
	x[u - 1] += 1
	x[v - 1] += 1
	a.append([u - 1, v - 1])
start = 0
end = n - 2
for (u, v) in a:
	if x[u] == 1 or x[v] == 1:
		print(start)
		start += 1
	else:
		print(end)
		end -= 1


from sys import *
from bisect import *
import math
from collections import *
from heapq import *
from itertools import *
inf = 10 ** 18
mod = 10 ** 9 + 7
n = int(input())
dic = defaultdict(int)
arr = []
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	dic[u] += 1
	dic[v] += 1
	arr.append((u, v))
deg = 0
search = [0, 0]
for i in dic:
	if dic[i] >= 3:
		search = [i, dic[i]]
		break
deg2 = search[1]
for i in arr:
	if i[0] == search[0] or i[1] == search[0]:
		print(deg)
		deg += 1
	else:
		print(deg2)
		deg2 += 1


import time, math
from sys import stdin, stdout
from collections import deque
import bisect
from fractions import Fraction
pi = 3.141592653589793

def I():
	return stdin.readline()

def In():
	return map(int, stdin.readline().split())

def L():
	return list(map(int, stdin.readline().split()))

def Si():
	return sorted(list(map(int, stdin.readline().split())))

def Si():
	return sorted(list(map(int, stdin.readline().split())), reverse=True)

def P(x):
	return stdout.write(str(x) + '\n')

def Pi(x, y):
	return stdout.write(str(x) + ' ' + str(y) + '\n')

def lcm(a, b):
	return a * b // gcd(a, b)

def gcd(a, b):
	if a == 0:
		return b
	elif b == 0:
		return a
	if a > b:
		return gcd(a % b, b)
	else:
		return gcd(a, b % a)

def readTree():
	v = int(input())
	li = [set() for i in range(v + 1)]
	l = []
	for i in range(v - 1):
		(u1, u2) = In()
		li[u1].add(u2)
		li[u2].add(u1)
		l.append([u1, u2])
	return (li, v, l)

def bfs(adj, v):
	visited = [False] * (v + 1)
	visited[1] = True
	q = deque()
	q.append(1)
	while q:
		ele = q.pop()
		if len(adj[ele]) >= 3:
			note = ele
			return (True, note)
		for sml in adj[ele]:
			if visited[sml] == False:
				q.append(sml)
				visited[sml] = True
	return (False, -1)

def solve():
	(adj, v, l) = readTree()
	(stm, val) = bfs(adj, v)
	if stm == False:
		li = [i for i in range(v - 1)]
		for ele in li:
			P(ele)
	else:
		u = [0, 1, 2]
		avail = [i for i in range(3, v - 1)]
		for ele in l:
			(u1, u2) = (ele[0], ele[1])
			if u1 == val or u2 == val:
				if u:
					print(u.pop())
				else:
					print(avail.pop())
			else:
				print(avail.pop())
solve()


from collections import defaultdict
N = int(input())
arr = [0] * (N + 1)
Dict = {}
List = []
for _ in range(N - 1):
	(i, j) = map(int, input().split())
	List.append([i, j])
	arr[i] += 1
	arr[j] += 1
count = 0
ans = [-1] * (N - 1)
for i in range(N - 1):
	if arr[List[i][0]] == 1 or arr[List[i][1]] == 1:
		ans[i] = count
		count += 1
for i in range(N - 1):
	if ans[i - 1] == -1:
		ans[i - 1] = count
		count += 1
for i in range(N - 1):
	print(ans[i])


import sys
readline = sys.stdin.readline

def i1():
	return int(readline())

def nl():
	return [int(s) for s in readline().split()]

def nn(n):
	return [int(readline()) for i in range(n)]

def nnp(n, x):
	return [int(readline()) + x for i in range(n)]

def nmp(n, x):
	return (int(readline()) + x for i in range(n))

def nlp(x):
	return [int(s) + x for s in readline().split()]

def nll(n):
	return [[int(s) for s in readline().split()] for i in range(n)]

def mll(n):
	return ([int(s) for s in readline().split()] for i in range(n))

def s1():
	return readline().rstrip()

def sl():
	return [s for s in readline().split()]

def sn(n):
	return [readline().rstrip() for i in range(n)]

def sm(n):
	return (readline().rstrip() for i in range(n))

def redir(s):
	global readline
	import os
	fn = sys.argv[0] + f'/../in-{s}.txt'
	readline = open(fn).readline if os.path.exists(fn) else readline
import os
if 'DEPTH' in os.environ:

	def printd(*a, **aa):
		print(*a, **aa)
else:

	def printd(*a, **aa):
		pass
redir('c')
n = i1()
nodes = [[] for i in range(n)]
for i in range(n - 1):
	(u, v) = nlp(-1)
	nodes[u].append((v, i))
	nodes[v].append((u, i))
printd(nodes)
printd([len(i) for i in nodes])
h3 = set()
for i in (nodes[i][0] for i in range(n) if len(nodes[i]) == 1):
	h3.add(i[1])
	if len(h3) == 3:
		break
labels = [-1] * (n - 1)
printd('h3', h3)
printd('labels', labels)
for (i, h) in enumerate(h3):
	labels[h] = i
printd('labels', labels)
j = len(h3)
for i in range(n - 1):
	if labels[i] < 0:
		labels[i] = j
		j += 1
printd(h3)
printd(labels)
print('\n'.join((str(i) for i in labels)))


n = int(input())
g = [[] for _ in range(n)]
ans = [-1] * (n - 1)
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	g[u - 1].append(_)
	g[v - 1].append(_)
cnt = 3
for i in range(n):
	if len(g[i]) >= 3:
		for j in range(3):
			ans[g[i][j]] = j
		break
else:
	cnt = 0
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = cnt
		cnt += 1
for x in ans:
	print(x)


from bisect import bisect_left as bl, bisect_right as br, insort
import sys
import heapq
from math import *
from collections import defaultdict as dd, deque

def data():
	return sys.stdin.readline().strip()

def mdata():
	return map(int, data().split())
n = int(input())
t = [dd(int) for i in range(n)]
l = []
for i in range(n - 1):
	(u, v) = mdata()
	t[u - 1][v - 1] = 0
	t[v - 1][u - 1] = 0
	l.append([u - 1, v - 1])
s = 0
e = n - 2
for i in range(n - 1):
	(a, b) = l[i]
	if len(t[a]) == 1 or len(t[b]) == 1:
		print(s)
		s += 1
	else:
		print(e)
		e -= 1


n = int(input())
N = []
X = [0] * (n + 1)
for i in range(n - 1):
	ch = input()
	L = [int(i) for i in ch.split()]
	a = L[0]
	b = L[1]
	N.append((a, b))
	X[a] += 1
	X[b] += 1
nb1 = 0
for i in range(n + 1):
	if X[i] == 1:
		nb1 += 1
i = 0
j = nb1
for k in range(n - 1):
	if X[N[k][0]] == 1 or X[N[k][1]] == 1:
		print(i)
		i += 1
	else:
		print(j)
		j += 1


di = {}
edLi = []
n = int(input())
deg = []
for i in range(0, n + 1):
	deg.append(0)
for _ in range(n - 1):
	liStr = input().split()
	a = int(liStr[0])
	b = int(liStr[1])
	tempLi = []
	tempLi.append(a)
	tempLi.append(b)
	edLi.append(tuple(tempLi))
	deg[a] += 1
	deg[b] += 1
degree3Node = 0
x = 3
for i in range(len(deg)):
	if deg[i] >= 3:
		degree3Node = i
		x = deg[i]
		break
p = x
q = 0
if n > 2:
	if degree3Node == 0:
		for i in range(0, n - 1):
			print(i)
	else:
		for i in range(0, n - 1):
			if degree3Node in edLi[i]:
				print(q)
				q += 1
			else:
				print(p)
				p += 1
else:
	print(0)


n = int(input())
a = [0 for _ in range(n)]
e = []
bl = [0] * n
cnt = 1
if n == 2:
	print(0)
	exit()
for i in range(n - 1):
	(boof1, boof2) = map(int, input().split())
	boof1 -= 1
	boof2 -= 1
	a[boof1] += 1
	a[boof2] += 1
	e.append((boof1, boof2))
for i in range(n):
	if a[i] == 1:
		bl[i] = cnt
		cnt += 1
cnt2 = cnt
for i in range(n - 1):
	if bl[e[i][0]] != 0 or bl[e[i][1]] != 0:
		print(bl[e[i][0]] + bl[e[i][1]] - 1)
	else:
		print(cnt2 - 1)
		cnt2 += 1


import math
q = 1
for _ in range(q):
	n = int(input())
	count = [0] * 100005
	arr = []
	for i in range(n - 1):
		(a, b) = map(int, input().split())
		count[a] += 1
		count[b] += 1
		arr.append([a, b])
	ans = []
	u = 0
	v = n - 2
	for i in range(len(arr)):
		if count[arr[i][0]] == 1 or count[arr[i][1]] == 1:
			ans.append(u)
			u += 1
		else:
			ans.append(v)
			v -= 1
	print('\n'.join(list(map(str, ans))))


n = int(input())
graph = {}
for i in range(n):
	graph[i + 1] = []
edges = []
for i in range(n - 1):
	(a, b) = map(int, input().split())
	graph[a].append(b)
	graph[b].append(a)
	edges.append([a, b])
big = 0
node = 0
for i in range(n):
	if len(graph[i + 1]) > 2:
		node = i + 1
		big = 1
if big == 0:
	counter = 0
	for i in range(n - 1):
		print(counter)
		counter += 1
else:
	counter = 3
	counter2 = 0
	for i in edges:
		if i[0] == node or i[1] == node:
			if counter2 < 3:
				print(counter2)
				counter2 += 1
			else:
				print(counter)
				counter += 1
		else:
			print(counter)
			counter += 1


from collections import defaultdict, deque
El = []
Er = []
En = []
N = int(input())
g = [[0] for _ in range(N + 1)]
dist = [2 ** 20 for _ in range(N + 1)]
visited = [0] * (N + 1)
for num in range(N - 1):
	(u, v) = list(map(int, input().split()))
	g[u][0] += 1
	g[u].append(v)
	g[v][0] += 1
	g[v].append(u)
	El.append(v)
	Er.append(u)
	En.append(num)
order = []
s = deque([1])
while s:
	v = s.pop()
	visited[v] = 1
	order.append(v)
	for i in g[v][1:]:
		if not visited[i]:
			s.append(i)
for u in reversed(order):
	if g[u][0] == 1:
		dist[u] = 0
	else:
		dist[u] = min([dist[u]] + [dist[v] + 1 for v in g[u][1:]])
for u in order:
	if g[u][0] == 1:
		dist[u] = 0
	else:
		prdist = dist[u]
		dist[u] = min([dist[u]] + [dist[v] + 1 for v in g[u][1:]])
		if dist[u] == prdist:
			break
keys = [dist[el] + dist[er] for (el, er) in zip(El, Er)]
X = [(e, n) for (n, e) in enumerate(sorted(En, key=lambda x: keys[x]))]
print('\n'.join([str(i) for (_, i) in sorted(X)]))


import sys
readline = sys.stdin.readline

def parorder(Edge, p):
	N = len(Edge)
	par = [0] * N
	par[p] = -1
	stack = [p]
	order = []
	visited = set([p])
	ast = stack.append
	apo = order.append
	while stack:
		vn = stack.pop()
		apo(vn)
		for vf in Edge[vn]:
			if vf in visited:
				continue
			visited.add(vf)
			par[vf] = vn
			ast(vf)
	return (par, order)

def getcld(p):
	res = [[] for _ in range(len(p))]
	for (i, v) in enumerate(p[1:], 1):
		res[v].append(i)
	return res
N = int(readline())
Edge = [[] for _ in range(N)]
Dim = [0] * N
for m in range(N - 1):
	(a, b) = map(int, readline().split())
	a -= 1
	b -= 1
	Edge[a].append((m, b))
	Edge[b].append((m, a))
	Dim[a] += 1
	Dim[b] += 1
if max(Dim) <= 2:
	print('\n'.join(map(str, range(N - 1))))
else:
	k = Dim.index(max(Dim))
	Ans = [None] * (N - 1)
	remain = set(range(N - 1))
	cnt = 0
	for (m, vf) in Edge[k]:
		Ans[m] = cnt
		remain.remove(cnt)
		cnt += 1
	for i in range(N - 1):
		if Ans[i] is None:
			Ans[i] = remain.pop()
	print('\n'.join(map(str, Ans)))


import sys
import heapq
from math import ceil, floor, gcd, fabs, factorial, fmod, sqrt
from collections import defaultdict as dd, deque, Counter as c
from itertools import combinations as comb, permutations as perm
from bisect import bisect_left as bl, bisect_right as br, bisect
mod = pow(10, 9) + 7
mod2 = 998244353

def data():
	return sys.stdin.readline().strip()

def out(var):
	sys.stdout.write(str(var))

def l():
	return list(sp())

def sl():
	return list(ssp())

def sp():
	return map(int, data().split())

def ssp():
	return map(str, data().split())

def l1d(n, val=0):
	return [val for i in range(n)]

def l2d(n, m, val=0):
	return [[val for i in range(n)] for j in range(m)]

def maxDeg():
	for i in graph.keys():
		if len(graph[i]) >= 3:
			return i
	return 0
n = int(data())
graph = dd(set)
mat = []
for i in range(n - 1):
	(a, b) = sp()
	mat.append((a, b))
	graph[a].add(b)
	graph[b].add(a)
m = maxDeg()
(dist, length, j) = (len(graph[m]) - 1, len(graph[m]) - 1, 1)
for i in mat:
	if i[0] == m and dist >= 0:
		out(str(length - dist) + '\n')
		dist -= 1
	elif i[1] == m and dist >= 0:
		out(str(length - dist) + '\n')
		dist -= 1
	else:
		out(str(length + j) + '\n')
		j += 1


import atexit
import io
import sys
_INPUT_LINES = sys.stdin.read().splitlines()
input = iter(_INPUT_LINES).__next__
_OUTPUT_BUFFER = io.StringIO()
sys.stdout = _OUTPUT_BUFFER

@atexit.register
def write():
	sys.__stdout__.write(_OUTPUT_BUFFER.getvalue())
data = input().rstrip().split()
n = int(data[0])
edges = []
g = {i + 1: [] for i in range(n)}
leafes = set()
for _ in range(n - 1):
	data = input().rstrip().split()
	(a, b) = (int(data[0]), int(data[1]))
	(a, b) = sorted([a, b])
	edges.append((a, b))
	g[a].append(b)
	g[b].append(a)
for (k, v) in g.items():
	if len(leafes) == 3:
		break
	if len(v) == 1:
		e = sorted([k, v[0]])
		leafes.add(tuple(e))
counter = len(leafes)
l_counter = 0
to_print = []
for edge in edges:
	(a, b) = edge
	if edge in leafes:
		to_print.append(l_counter)
		l_counter += 1
	else:
		to_print.append(counter)
		counter += 1
for p in to_print:
	print(p)


import sys

def main():
	n = int(sys.stdin.readline())
	adj = [[] for i in range(n)]
	st = 0
	d = dict()
	for i in range(n - 1):
		(u, v) = [int(j) - 1 for j in sys.stdin.readline().split()]
		d[u, v] = '#'
		adj[u].append(v)
		adj[v].append(u)
		if len(adj[u]) > 2:
			st = u
		elif len(adj[v]) > 2:
			st = v
	stack = [st]
	ct = 0
	visited = set()
	while len(stack) > 0:
		v = stack.pop()
		visited.add(v)
		for nb in adj[v]:
			if nb not in visited:
				if (nb, v) in d:
					d[nb, v] = str(ct)
					ct += 1
				elif (v, nb) in d:
					d[v, nb] = str(ct)
					ct += 1
				stack.append(nb)
	sys.stdout.write('\n'.join(list(d.values())))
main()


n = int(input())
nodes = [[] for _ in range(n + 2)]
for i in range(n - 1):
	(a, b) = [int(x) for x in input().split()]
	nodes[a].append(i)
	nodes[b].append(i)
max_node = max(range(1, n + 1), key=lambda x: len(nodes[x]))
ans = [None] * (n - 1)
cur = 0
for i in nodes[max_node]:
	ans[i] = cur
	cur += 1
for i in range(n - 1):
	if ans[i] is None:
		ans[i] = cur
		cur += 1
print('\n'.join([str(x) for x in ans]))


from sys import stdin
import sys
tt = 1
for loop in range(tt):
	n = int(stdin.readline())
	lis = [[] for i in range(n)]
	for i in range(n - 1):
		(u, v) = map(int, stdin.readline().split())
		u -= 1
		v -= 1
		lis[u].append((v, i))
		lis[v].append((u, i))
	one = []
	for i in range(n):
		if len(lis[i]) == 1:
			one.append(i)
	ans = [None] * (n - 1)
	cnt = 0
	for i in one:
		for (v, ind) in lis[i]:
			if ans[ind] == None:
				ans[ind] = cnt
				cnt += 1
	for i in range(n - 1):
		if ans[i] == None:
			ans[i] = cnt
			cnt += 1
	print('\n'.join(map(str, ans)))


n = int(input())
l = []
for i in range(n - 1):
	s = input().split()
	l.append((i, int(s[0]) - 1, int(s[1]) - 1))
g = []
for i in range(n):
	g.append(0)
for x in l:
	g[x[1]] = g[x[1]] + 1
	g[x[2]] = g[x[2]] + 1
i = 0
r = -1
while i < n:
	if g[i] > 2:
		r = i
	i = i + 1

def h(j, r):
	return (l[j][1] == r) | (l[j][2] == r)
if r == -1:
	for j in range(n - 1):
		print(j)
else:
	j = 0
	t1 = 0
	t2 = 3
	while j < n - 1:
		if h(j, r) & (t1 < 3):
			print(t1)
			t1 = t1 + 1
		else:
			print(t2)
			t2 = t2 + 1
		j = j + 1


import sys
input = sys.stdin.readline
n = int(input())
G = [[] for _ in range(n)]
edges = []
for edge in range(n - 1):
	(u, v) = map(int, input().split())
	u -= 1
	v -= 1
	G[u].append((u, v))
	G[v].append((u, v))
	edges.append((u, v))
for node in range(n):
	if len(G[node]) >= 3:
		special = G[node][:3]
		out = []
		count = 3
		for edge in edges:
			if edge in special:
				out.append(str(special.index(edge)))
				continue
			out.append(str(count))
			count += 1
		print('\n'.join(out))
		exit(0)
out = []
for i in range(n - 1):
	out.append(str(i))
print('\n'.join(out))


import sys
import os
import time
import collections
from collections import Counter, deque
import itertools
import math
import timeit
import random
from io import BytesIO, IOBase
from bisect import bisect_left as bl
from bisect import bisect_right as br

def sieve(n):
	if n < 2:
		return list()
	prime = [True for _ in range(n + 1)]
	p = 3
	while p * p <= n:
		if prime[p]:
			for i in range(p * 2, n + 1, p):
				prime[i] = False
		p += 2
	r = [2]
	for p in range(3, n + 1, 2):
		if prime[p]:
			r.append(p)
	return r

def divs(n, start=1):
	divisors = []
	for i in range(start, int(math.sqrt(n) + 1)):
		if n % i == 0:
			if n / i == i:
				divisors.append(i)
			else:
				divisors.extend([i, n // i])
	return divisors

def divn(n, primes):
	divs_number = 1
	for i in primes:
		if n == 1:
			return divs_number
		t = 1
		while n % i == 0:
			t += 1
			n //= i
		divs_number *= t

def flin(d, x, default=-1):
	left = right = -1
	for i in range(len(d)):
		if d[i] == x:
			if left == -1:
				left = i
			right = i
	if left == -1:
		return (default, default)
	else:
		return (left, right)

def modpow(b, p, m):
	res = 1
	b = b % m
	while p:
		if p & 1:
			res = res * b % m
		b = b * b % m
		p >>= 1
	return res

def mod_inv(a, m):
	return modpow(a, m - 2, m)

def ncr(n, r, m):
	res = 1
	if r == 0:
		return 1
	if n - r < r:
		r = n - r
	(p, k) = (1, 1)
	while r:
		res = res % m * (n % m * mod_inv(r, m) % m) % m
		n -= 1
		r -= 1
	return res

def ncrlis(n, r, m, fact):
	return fact[n] * (mod_inv(fact[r], m) * mod_inv(fact[n - r], m)) % m % m

def ceil(n, k):
	return n // k + (n % k != 0)

def ii():
	return int(input())

def mi():
	return map(int, input().split())

def li():
	return list(map(int, input().split()))

def lcm(a, b):
	return abs(a * b) // math.gcd(a, b)

def prr(a, sep=' '):
	print(sep.join(map(str, a)))

def dd():
	return collections.defaultdict(int)

def ddl():
	return collections.defaultdict(list)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from collections import OrderedDict
n = ii()
d = dd()
t = OrderedDict()
res = []
for i in range(n - 1):
	(u, v) = mi()
	t.setdefault((u, v), -1)
	d[u] += 1
	d[v] += 1
for k in d:
	if d[k] == 1:
		res.append(k)
num = 0
for k in t:
	if d[k[0]] == 1 or d[k[1]] == 1:
		t[k] = num
		num += 1
for k in t:
	if t[k] == -1:
		t[k] = num
		num += 1
for k in t:
	print(t[k])


n = int(input())
a = [0] * n
pos = -1
c = []
for i in range(0, n - 1):
	(u, v) = map(int, input().split())
	c.append([u, v])
for i in range(0, n - 1):
	a[c[i][0] - 1] += 1
	a[c[i][1] - 1] += 1
	if a[c[i][0] - 1] >= 3:
		pos = c[i][0]
		break
	if a[c[i][1] - 1] >= 3:
		pos = c[i][1]
		break
ans = [-1] * (n - 1)
count = 3
if pos != -1:
	for i in range(0, n - 1):
		if c[i][0] == pos or c[i][1] == pos:
			ans[i] = count - 1
			count -= 1
			if count == 0:
				break
count = 3
if pos == -1:
	count -= 3
for i in range(0, n - 1):
	if ans[i] == -1:
		ans[i] = count
		count += 1
for i in range(0, n - 1):
	print(ans[i])


def solve(graph):
	ans = [-1 for i in range(len(graph) - 1)]
	for v in graph:
		if len(graph[v]) > 2:
			for (i, (u, k)) in enumerate(graph[v][:3]):
				ans[k] = i
			k = 0
			for i in range(3, len(ans)):
				while ans[k] != -1:
					k += 1
				ans[k] = i
			return ans
	return list(range(len(graph) - 1))

def test():
	g1 = {1: [(2, 0), (3, 1)], 2: [(1, 0)], 3: [(1, 1)]}
	s1 = solve(g1)
	print(s1)
	assert s1 == [0, 1]
	g2 = {1: [(2, 0), (3, 1)], 2: [(1, 0), (4, 2), (5, 3)], 3: [(1, 1)], 4: [(2, 2)], 5: [(2, 3), (6, 5)], 6: [(5, 5)]}
	s2 = solve(g2)
	print(s2)
	assert s2 == [0, 3, 1, 2, 4]
n = int(input())
graph = {i: [] for i in range(1, n + 1)}
edges = []
for i in range(n - 1):
	(u, v) = [int(c) for c in input().split()]
	graph[u].append((v, i))
	graph[v].append((u, i))
ans = solve(graph)
print(*ans, sep='\n')


n = int(input())
a = [0] * n
g = []
for _ in range(n - 1):
	(x, y) = map(int, input().split())
	x -= 1
	y -= 1
	a[x] += 1
	a[y] += 1
	g.append([x, y])
(m1, m2) = (0, n - 2)
for (x, y) in g:
	if a[x] == 1 or a[y] == 1:
		print(m1)
		m1 += 1
	else:
		print(m2)
		m2 -= 1


from collections import deque

def main():
	n = int(input())
	graph = []
	for i in range(n):
		graph.append(set())
	edges_list = []
	for i in range(n - 1):
		edges_list.append(tuple(map(lambda x: int(x) - 1, input().split())))
		graph[edges_list[-1][0]].add(edges_list[-1][1])
		graph[edges_list[-1][1]].add(edges_list[-1][0])
	queue_of_vertex = deque()
	for i in range(n):
		if len(graph[i]) == 1:
			queue_of_vertex.append(i)
	count = 0
	edges = {}
	while len(queue_of_vertex) > 0:
		vertex = queue_of_vertex.popleft()
		for to in graph[vertex]:
			graph[to].remove(vertex)
			edges[vertex, to] = count
			edges[to, vertex] = count
			count += 1
			if len(graph[to]) == 1:
				queue_of_vertex.append(to)
		graph[vertex].clear()
	for element in edges_list:
		print(edges[element])
main()


import sys
input = sys.stdin.buffer.readline
n = int(input())
nodes = {i: 0 for i in range(1, n + 1)}
q = []
needednode = -1
for i in range(n - 1):
	(a, b) = [int(c) for c in input().split()]
	q.append((a, b))
	nodes[a] += 1
	if nodes[a] >= 3:
		needednode = a
	nodes[b] += 1
	if nodes[b] >= 3:
		needednode = b
if needednode == -1:
	for i in range(len(q)):
		print(i)
else:
	first = 0
	second = 3
	for (a, b) in q:
		if first < 3 and (a == needednode or b == needednode):
			print(first)
			first += 1
		else:
			print(second)
			second += 1


n = int(input())
a = [0] * n
b = [0] * n
c = [0] * (n + 1)
d = [-1] * (n + 1)
for i in range(n - 1):
	(a[i], b[i]) = map(int, input().split())
	c[a[i]] += 1
	c[b[i]] += 1
ok = 0
k = 0
for i in range(1, n + 1):
	if c[i] > 2:
		ok = 1
		for j in range(n - 1):
			if a[j] == i or b[j] == i:
				d[j] = k
				k += 1
		break
for j in range(n - 1):
	if d[j] == -1:
		print(k)
		k += 1
	else:
		print(d[j])


n = int(input())
freqs = [0 for i in range(n)]
uv_pairs = []
for i in range(n - 1):
	(u, v) = map(int, input().split())
	u -= 1
	v -= 1
	freqs[u] += 1
	freqs[v] += 1
	uv_pairs.append((u, v))
mn = 0
mx = n - 2
for i in range(n - 1):
	(u, v) = uv_pairs[i]
	if freqs[u] == 1 or freqs[v] == 1:
		print(mn)
		mn += 1
	else:
		print(mx)
		mx -= 1


import math
import time
from collections import defaultdict, deque
from sys import stdin, stdout
from bisect import bisect_left, bisect_right, bisect
n = int(input())
graph = defaultdict(lambda : [])
edges = []
for i in range(n - 1):
	(a, b) = map(int, stdin.readline().split())
	graph[a].append(b)
	graph[b].append(a)
	edges.append([a, b])
ma = 0
mi = 0
for i in graph.keys():
	if len(graph[i]) > ma:
		ma = len(graph[i])
		mi = i
if ma > 2:
	special = set()
	for i in graph[mi][:3]:
		special.add(tuple([mi, i]))
	scount = 0
	rest = 3
	for i in edges:
		if tuple(i) in special or tuple(i[::-1]) in special:
			print(scount)
			scount += 1
		else:
			print(rest)
			rest += 1
else:
	for i in range(n - 1):
		print(i)


n = int(input())
categories_to_nodes = {0: {i for i in range(1, n + 1)}, 1: set(), 2: set()}
all_data = []
for edge in range(n - 1):
	data = input().split()
	all_data.append(data)
	if int(data[0]) in categories_to_nodes[0]:
		categories_to_nodes[0].remove(int(data[0]))
		categories_to_nodes[1].add(int(data[0]))
	elif int(data[0]) in categories_to_nodes[1]:
		categories_to_nodes[1].remove(int(data[0]))
		categories_to_nodes[2].add(int(data[0]))
	if int(data[1]) in categories_to_nodes[0]:
		categories_to_nodes[0].remove(int(data[1]))
		categories_to_nodes[1].add(int(data[1]))
	elif int(data[1]) in categories_to_nodes[1]:
		categories_to_nodes[1].remove(int(data[1]))
		categories_to_nodes[2].add(int(data[1]))
leaves = categories_to_nodes[1]
if len(leaves) == 2:
	for i in range(n - 1):
		print(i)
else:
	i = n - 2
	j = 0
	for data in all_data:
		if int(data[0]) in leaves or int(data[1]) in leaves:
			print(j)
			j += 1
		else:
			print(i)
			i -= 1


import sys
input = sys.stdin.readline
n = int(input())
adj_list = [[] for _ in range(n)]
intial_arr = []
for _ in range(n - 1):
	(a, b) = map(int, input().split())
	intial_arr.append([a - 1, b - 1])
	adj_list[a - 1].append(b - 1)
	adj_list[b - 1].append(a - 1)
l = 0
ans = {}
for i in range(n):
	if len(adj_list[i]) >= 3:
		for k in adj_list[i]:
			ans[k, i] = l
			ans[i, k] = l
			l += 1
		break
for a in intial_arr:
	if (a[0], a[1]) in ans:
		print(ans[a[0], a[1]])
	elif (a[1], a[0]) in ans:
		print(ans[a[1], a[0]])
	else:
		print(l)
		l += 1


n = int(input())
graph = [[] for _ in range(n)]
edges = []
for _ in range(n - 1):
	(a, b) = map(int, input().split())
	a = a - 1
	b = b - 1
	edges.append((a, b))
	graph[a].append(b)
	graph[b].append(a)
count = 0
c = 0
ans = {}
for edge in edges:
	if len(graph[edge[0]]) == 1 or len(graph[edge[1]]) == 1:
		ans[edge] = c
		c += 1
for edge in edges:
	if edge not in ans:
		ans[edge] = c
		c += 1
	print(ans[edge])


from sys import stdout
n = int(input())
a = [[] for i in range(n)]
e = []
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	a[u - 1].append(v - 1)
	a[v - 1].append(u - 1)
	e.append([u - 1, v - 1])
ans = [-1] * (n - 1)
k = 0
for i in range(n - 1):
	if len(a[e[i][1]]) == 1 or len(a[e[i][0]]) == 1:
		ans[i] = k
		k += 1
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = k
		k += 1
for i in ans:
	stdout.write(str(i) + '\n')


class Node:

	def __init__(self, val):
		self.left = None
		self.right = None
		self.value = val

class Tree:

	def __init__(self, n):
		self.root = None
		self.size = n

def mex(u, v):
	if max(u) > max(v):
		return u
	return v

def main():
	n = int(input())
	v = dict()
	ans = [-1]
	for i in range(1, n):
		v[i] = []
		ans.append(-1)
	for i in range(1, n):
		(a, b) = [int(v) for v in input().split()]
		if not a in v:
			v[a] = []
		v[a].append(i)
		if not b in v:
			v[b] = []
		v[b].append(i)
	mx = (0, 0)
	for i in range(1, n):
		mx = max(mx, (len(v[i]), i))
	cur = 0
	for i in v[mx[1]]:
		ans[i] = cur
		cur += 1
	for i in range(1, n):
		if ans[i] == -1:
			ans[i] = cur
			cur += 1
		print(ans[i])
main()


from sys import stdin, stdout, setrecursionlimit
import heapq
from math import gcd, ceil, sqrt
from collections import Counter, deque
from bisect import bisect_left, bisect_right
from itertools import combinations, permutations
ii1 = lambda : int(stdin.readline().strip())
is1 = lambda : stdin.readline().strip()
iia = lambda : list(map(int, stdin.readline().strip().split()))
isa = lambda : stdin.readline().strip().split()
setrecursionlimit(100000)
mod = 1000000007
n = ii1()
cnt = [0] * n
edges = []
for i in range(n - 1):
	(a, b) = iia()
	cnt[a - 1] += 1
	cnt[b - 1] += 1
	edges.append([a - 1, b - 1])
(cur, end) = (0, n - 2)
for i in edges:
	if cnt[i[0]] > 1 and cnt[i[1]] > 1:
		print(end)
		end -= 1
	else:
		print(cur)
		cur += 1


n = int(input())
e = [[] for _ in range(n + 1)]
ec = [0 for _ in range(n + 1)]
done = False
for i in range(n - 1):
	(a, b) = map(int, input().split())
	if done:
		continue
	e[a].append(i)
	e[b].append(i)
	ec[a] += 1
	ec[b] += 1
	soll = []
	if ec[a] >= 3:
		soll = e[a]
		done = True
	elif ec[b] >= 3:
		soll = e[b]
		done = True
if not done:
	for i in range(n - 1):
		print(i)
else:
	x = 0
	y = 3
	for i in range(n - 1):
		if i in soll:
			print(x)
			x += 1
		else:
			print(y)
			y += 1


from __future__ import division, print_function
import os
import sys
from io import BytesIO, IOBase
from itertools import permutations, combinations
from collections import defaultdict, deque, OrderedDict
from os import path
import random
import bisect as bi

def yes():
	print('YES')

def no():
	print('NO')

def I():
	return int(input())

def In():
	return map(int, input().split())

def main():
	try:
		n = I()
		d = defaultdict(list)
		ans = -1
		d1 = {}
		l = []
		for x in range(n - 1):
			(a, b) = In()
			d[a].append(b)
			d[b].append(a)
			temp = (min(a, b), max(a, b))
			l.append(temp)
			d1[temp] = -1
			if len(d[a]) >= 3:
				ans = a
			elif len(d[b]) >= 3:
				ans = b
		if ans == -1:
			for i in range(n - 1):
				print(i)
		else:
			i = 0
			for x in d[ans]:
				temp = (min(x, ans), max(x, ans))
				d1[temp] = i
				i += 1
			for j in l:
				if d1[j] == -1:
					d1[j] = i
					i += 1
			for x in l:
				print(d1[x])
	except:
		pass
M = 998244353
P = 1000000007
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
for _ in range(1):
	main()


from sys import stdin
n = int(input())
e = []
ad = [[] for _ in range(n)]
for _ in range(n - 1):
	(a, b) = map(int, stdin.readline().split())
	a -= 1
	b -= 1
	e.append((a, b))
	ad[a].append(b)
	ad[b].append(a)
three = {}
for x in range(n):
	if len(ad[x]) > 2:
		for i in range(3):
			three[x, ad[x][i]] = three[ad[x][i], x] = i
		break
i = n - 2
for x in e:
	if x in three:
		print(three[x])
	else:
		print(i)
		i -= 1


import sys

def func(n, graph, kaunsa, d):
	cnt = 0
	ans = []
	for i in range(1, n + 1):
		if len(graph[i]) == 1:
			cnt += 1
	if cnt < 3:
		for i in range(n - 1):
			ans.append(i)
	else:
		for i in range(1, n + 1):
			if len(graph[i]) == 1:
				not_found = str(i) + ' ' + str(graph[i][0])
				q = str(graph[i][0]) + ' ' + str(i)
				if not_found in d:
					d[not_found] = 10 ** 10
				else:
					d[q] = 10 ** 10
		here = cnt
		come = 0
		for i in kaunsa:
			if d[i] != 10 ** 10:
				ans.append(here)
				here += 1
			else:
				ans.append(come)
				come += 1
	for i in ans:
		sys.stdout.write(str(i) + '\n')
n = int(sys.stdin.readline().rstrip().lstrip())
graph = [[] for i in range(n + 1)]
kaunsa = []
d = {}
for i in range(n - 1):
	(u, v) = list(map(int, sys.stdin.readline().rstrip().lstrip().split()))
	graph[u].append(v)
	graph[v].append(u)
	d[str(u) + ' ' + str(v)] = 1
	kaunsa.append(str(u) + ' ' + str(v))
ans = func(n, graph, kaunsa, d)


import os
import sys
import math
from io import BytesIO, IOBase
from fractions import Fraction
import collections
from itertools import permutations
from collections import defaultdict
from collections import deque
import threading
threading.stack_size(10 ** 8)
sys.setrecursionlimit(300000)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def main():
	n = int(input())
	graph = defaultdict(list)
	edge = list()
	d = dict()
	for i in range(n - 1):
		(x, y) = map(int, input().split())
		graph[x - 1].append(y - 1)
		graph[y - 1].append(x - 1)
		edge.append((x, y))
	mx = 0
	for i in range(n - 1):
		l = len(graph[i])
		mx = max(mx, l)
		if l >= 3:
			for j in range(3):
				d[i + 1, graph[i][j] + 1] = j
			break
	c = 0
	if mx >= 3:
		c = 3
	for i in range(n - 1):
		(x, y) = edge[i]
		if (x, y) in d:
			print(d[x, y])
		elif (y, x) in d:
			print(d[y, x])
		else:
			print(c)
			c += 1
t = threading.Thread(target=main)
t.start()
t.join()


n = int(input())
deg = [0] * (n + 2)
es = []
for i in range(n - 1):
	(a, b) = list(map(int, input().split()))
	deg[a] += 1
	deg[b] += 1
	es.append((a, b))
if max(deg) == 2:
	for i in range(n - 1):
		print(i)
else:
	k = deg.index(max(deg))
	e_012 = 0
	cnt = 3
	for e in es:
		if k in e and e_012 < 3:
			print(e_012)
			e_012 += 1
		else:
			print(cnt)
			cnt += 1


import bisect
import heapq
import math
import random
import sys
from collections import Counter, defaultdict, deque
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations
from operator import add, mul, sub
sys.setrecursionlimit(100000)
input = sys.stdin.readline
INF = 2 ** 62 - 1

def read_int():
	return int(input())

def read_int_n():
	return list(map(int, input().split()))

def read_float():
	return float(input())

def read_float_n():
	return list(map(float, input().split()))

def read_str():
	return input().strip()

def read_str_n():
	return list(map(str, input().split()))

def error_print(*args):
	print(*args, file=sys.stderr)

def mt(f):
	import time

	def wrap(*args, **kwargs):
		s = time.time()
		ret = f(*args, **kwargs)
		e = time.time()
		error_print(e - s, 'sec')
		return ret
	return wrap

@mt
def slv(N, UV):
	c = Counter()
	for (u, v) in UV:
		c[u] += 1
		c[v] += 1
	rn = 0
	for v in c.values():
		if v == 1:
			rn += 1
	ri = 0
	nri = rn
	ans = []
	for (u, v) in UV:
		if c[u] == 1 or c[v] == 1:
			ans.append(ri)
			ri += 1
		else:
			ans.append(nri)
			nri += 1
	return ans

def main():
	N = read_int()
	UV = [read_int_n() for _ in range(N - 1)]
	print('\n'.join(map(str, slv(N, UV))))
main()


n = int(input())
degree = [0] * (10 ** 5 + 1)
edges = []
special_node = None
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	edges.append((u, v))
	degree[u] += 1
	degree[v] += 1
for u in range(n):
	if degree[u] >= 3:
		special_node = u
		break
(start, end) = (0, n - 2)
for (u, v) in edges:
	if u == special_node or v == special_node:
		print(start)
		start += 1
	else:
		print(end)
		end -= 1


def run():
	n = int(input())
	input_edges = dict()
	edges = dict()
	for i in range(n - 1):
		(a, b) = list(map(int, input().split()))
		input_edges[a, b] = i
		input_edges[b, a] = i
		if a in edges:
			edges[a].append(b)
		else:
			edges[a] = [b]
		if b in edges:
			edges[b].append(a)
		else:
			edges[b] = [a]
	degrees = dict()
	for i in range(1, n + 1):
		l = len(edges[i])
		if l in degrees:
			degrees[l].append(i)
		else:
			degrees[l] = [i]
	values_degrees = [-1] * (len(input_edges) // 2)
	start_degree = 0
	if 1 in degrees:
		for i in degrees[1]:
			node1 = i
			node2 = edges[i][0]
			j = input_edges[node1, node2]
			if values_degrees[j] == -1:
				values_degrees[j] = start_degree
				start_degree += 1
	for i in range(len(values_degrees)):
		if values_degrees[i] == -1:
			values_degrees[i] = start_degree
			start_degree += 1
		print(values_degrees[i])
run()


from sys import stdin
input = stdin.readline
for xoxo in range(1):
	for _ in range(1):
		n = int(input())
		t = []
		for i in range(n):
			t.append([])
		a = []
		for i in range(n - 1):
			(l, r) = map(int, input().split())
			t[l - 1].append(r - 1)
			t[r - 1].append(l - 1)
			a.append([min(l, r) - 1, max(l, r) - 1])
		ans = []
		k = -1
		for i in range(n):
			if len(t[i]) > 2:
				for j in range(3):
					ans.append([min(i, t[i][j]), max(i, t[i][j])])
				k = 0
				break
		if k == -1:
			for i in range(n - 1):
				print(i)
			exit()
		(k, p) = (3, 0)
		for i in range(n - 1):
			if a[i] in ans:
				print(p)
				p += 1
			else:
				print(k)
				k += 1


t = int(input()) - 1
d = {}
l = []
for i in range(t):
	(u, v) = map(int, input().split())
	l.append([u, v])
	if u not in d:
		d[u] = 1
	else:
		d[u] += 1
	if v not in d:
		d[v] = 1
	else:
		d[v] += 1
a = []
for i in l:
	a.append(min(d[i[0]], d[i[1]]))
ans = [-1] * t
temp = 0
for i in range(t):
	if a[i] == 1:
		ans[i] = temp
		temp += 1
for i in range(t):
	if ans[i] == -1:
		ans[i] = temp
		temp += 1
print(*ans)


n = int(input())
graph = {}
values = {}
order = []
for i in range(n):
	graph[i + 1] = []
	values[i] = -1
val = -1
for i in range(n - 1):
	a = input().split(' ')
	a[0] = int(a[0])
	a[1] = int(a[1])
	order.append(a)
	graph[a[0]].append(a[1])
	graph[a[1]].append(a[0])
	if len(graph[a[0]]) >= 3:
		val = a[0]
	if len(graph[a[1]]) >= 3:
		val = a[1]
if val == -1:
	for i in range(n - 1):
		print(i)
else:
	count = 0
	for i in range(n - 1):
		if order[i][0] == val or order[i][1] == val:
			values[i] = count
			count = count + 1
	for i in range(n):
		if values[i] == -1:
			values[i] = count
			count = count + 1
	for i in range(n - 1):
		print(values[i])


import sys
inp = sys.stdin.readline

def input():
	return inp().strip()

def iin():
	return int(input())

def lin():
	return list(map(int, input().split()))

def BFS(s, adj):
	level = []
	parent = {s: None}
	lv = 1
	u = [s]
	while u:
		nextu = []
		nx = []
		for i in u:
			for v in adj[i]:
				if v not in parent:
					parent[v] = i
					nx.append((i, v))
					nextu.append(v)
		level.append(nx)
		u = nextu.copy()
	level = level[::-1]
	ans = {}
	ch = 0
	for l in level:
		for p in l:
			ans[p] = ch
			ch += 1
	return ans

def main():
	from collections import defaultdict
	T = 1
	while T:
		T -= 1
		n = iin()
		e = [lin() for i in range(n - 1)]
		adj = [set() for i in range(n + 1)]
		for (i, j) in e:
			adj[i].add(j)
			adj[j].add(i)
		ch = 0
		ans = {}
		ln = defaultdict(set)
		for i in range(1, n + 1):
			l = len(adj[i])
			ln[l].add(i)
		while ln[1]:
			a = ln[1]
			ln[1] = set()
			for i in a:
				if not adj[i]:
					continue
				(x, y) = (i, list(adj[i])[0])
				ans[x, y] = ch
				ch += 1
				l = len(adj[y])
				adj[y].remove(x)
				adj[x] = set()
				if l > 1:
					ln[l].remove(y)
				l = len(adj[y])
				if l > 0:
					ln[l].add(y)
		for (i, j) in e:
			print(ans[i, j] if (i, j) in ans else ans[j, i])
main()


import sys
adj = {}
n = int(sys.stdin.readline())
temp = []
for _ in range(n - 1):
	(a, b) = sys.stdin.readline().split()
	a = int(a)
	b = int(b)
	temp.append(tuple(sorted((a, b))))
	if a in adj:
		adj[a].append(b)
	else:
		adj[a] = [b]
	if b in adj:
		adj[b].append(a)
	else:
		adj[b] = [a]
m = 0
for i in adj.keys():
	if len(adj[i]) > m:
		m = len(adj[i])
		root = i
mex = 0
ans = {}
for edge in adj[root]:
	ans[tuple(sorted((root, edge)))] = mex
	mex += 1
for i in temp:
	if i in ans:
		sys.stdout.write(str(ans[i]))
	else:
		sys.stdout.write(str(mex))
		mex += 1
	sys.stdout.write('\n')


n = int(input())
if n == 2:
	print(0)
	exit(0)
lis = [0] * (n + 1)
link = [0] * (n + 1)
prt = [3] * (n - 1)
for i in range(n - 1):
	(x, y) = (int(m) for m in input().split())
	link[x] = link[y] = i
	lis[x] += 1
	lis[y] += 1
pt = lis.index(1)
prt[link[pt]] = 1
pt = lis.index(1, pt + 1)
prt[link[pt]] = 0
if lis.count(1) > 2:
	prt[link[lis.index(1, pt + 1)]] = 2
k = n - 2
for i in prt:
	if i > 2:
		print(k)
		k = k - 1
	else:
		print(i)


from sys import stdin
from collections import deque
input = stdin.buffer.readline
n = int(input())
d = [0] * (n + 1)
g = [[] for _ in range(n + 1)]
l = []
for _ in range(1, n):
	(u, v) = map(int, input().split())
	l.append((u, v))
	g[u].append(v)
	g[v].append(u)
	d[u] += 1
	d[v] += 1
q = deque()
for i in range(1, n + 1):
	if d[i] == 1:
		q.append(i)
a = dict()
color = 0
while q:
	u = q.popleft()
	d[u] -= 1
	for v in g[u]:
		if (u, v) not in a:
			a[u, v] = a[v, u] = color
			color += 1
		d[v] -= 1
		if d[v] == 1:
			q.append(v)
print('\n'.join((str(a[_]) for _ in l)))


n = int(input())
v = [[] for i in range(n)]
ans = [-1 for i in range(n)]
for i in range(n - 1):
	(a, b) = map(int, input().split())
	v[a - 1].append(i)
	v[b - 1].append(i)
mx = [0, 0]
for i in range(n):
	mx = max(mx, [len(v[i]), i])
cur = 0
for i in v[mx[1]]:
	ans[i] = cur
	cur += 1
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = cur
		cur += 1
	print(ans[i])


from collections import defaultdict, Counter
from bisect import bisect, bisect_left
from math import sqrt, gcd, ceil, factorial
from heapq import heapify, heappush, heappop
MOD = 10 ** 9 + 7
inf = float('inf')
ans_ = []

def nin():
	return int(input())

def ninf():
	return int(file.readline())

def st():
	return input().strip()

def stf():
	return file.readline().strip()

def read():
	return list(map(int, input().strip().split()))

def readf():
	return list(map(int, file.readline().strip().split()))

def solve():
	ans_ = ''
	n = nin()
	deg = defaultdict(int)
	arr = []
	for i in range(n - 1):
		(u, v) = read()
		deg[u] += 1
		deg[v] += 1
		arr.append((u, v))
	x = 0
	m = n - 2
	s = defaultdict(int)
	for i in arr:
		(u, v) = i
		if deg[u] == 1 or deg[v] == 1:
			ans_ += str(x) + '\n'
			x += 1
		else:
			ans_ += str(m) + '\n'
			m -= 1
	print(ans_)
solve()


import sys, math
input = sys.stdin.readline

def getInts():
	return [int(s) for s in input().split()]

def getInt():
	return int(input())

def getStrs():
	return [s for s in input().split()]

def getStr():
	return input()

def listStr():
	return list(input())
import collections as col
import math

def solve():
	N = getInt()
	if N == 2:
		print(0)
		return
	graph = col.defaultdict(set)
	edges = dict()
	edge_list = []
	for n in range(N - 1):
		(U, V) = getInts()
		graph[U].add(V)
		graph[V].add(U)
		edges[U, V] = -1
		edge_list.append((U, V))
	max_size = 0
	flag = False
	for node in graph:
		if len(graph[node]) > 2:
			flag = True
			break
	next_ind = 0
	if flag:
		ns = []
		for neighbour in graph[node]:
			ns.append(neighbour)
			if len(ns) == 3:
				break
		for j in range(3):
			if (node, ns[j]) in edges:
				edges[node, ns[j]] = j
			else:
				edges[ns[j], node] = j
		next_ind = 3
	for edge in edge_list:
		if edges[edge] == -1:
			print(next_ind)
			next_ind += 1
		else:
			print(edges[edge])
	return
solve()


import os
import sys
import math
import bisect
from sys import stdin, stdout
from math import gcd, floor, sqrt, log
from collections import defaultdict, Counter
from bisect import bisect_left as bl, bisect_right as br
from itertools import combinations
sys.setrecursionlimit(100000000)
int_inp = lambda : int(input())
strng = lambda : input().strip()
jn = lambda x, l: x.join(map(str, l))
strl = lambda : list(input().strip())
mul = lambda : map(int, input().strip().split())
mulf = lambda : map(float, input().strip().split())
seq = lambda : list(map(int, input().strip().split()))
ceil = lambda x: int(x) if x == int(x) else int(x) + 1
ceildiv = lambda x, d: x // d if x % d == 0 else x // d + 1
flush = lambda : stdout.flush()
stdstr = lambda : stdin.readline()
stdint = lambda : int(stdin.readline())
stdpr = lambda x: stdout.write(str(x))
mod = 1000000007

def solve():
	n = int_inp()
	g = [0] * (n + 1)
	l = []
	for i in range(n - 1):
		(a, b) = mul()
		a -= 1
		b -= 1
		g[a] += 1
		g[b] += 1
		l.append([a, b])
	start = 0
	end = n - 2
	for (a, b) in l:
		if g[a] == 1 or g[b] == 1:
			print(start)
			start += 1
		else:
			print(end)
			end -= 1
solve()


n = int(input())
degree = [0] * n
edges = []
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	u -= 1
	v -= 1
	degree[u] += 1
	degree[v] += 1
	edges.append((u, v))
label = [None] * (n - 1)
root = max(range(n), key=degree.__getitem__)
count = 0
for i in range(n - 1):
	if root in edges[i]:
		label[i] = count
		count += 1
for i in range(n - 1):
	if label[i] is None:
		label[i] = count
		count += 1
for x in label:
	print(x)


import sys
import math
input = sys.stdin.readline
t = 1
for _ in range(t):
	n = int(input())
	d = {}
	fr = []
	to = []
	for i in range(1, n + 1):
		d[i] = []
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		d[u].append(v)
		d[v].append(u)
		fr.append(u)
		to.append(v)
	weight = {}
	k = 0
	for i in range(1, n + 1):
		if len(d[i]) == 1:
			weight[i] = k
			k += 1
	if n == 2:
		weight[1] = 0
		weight[2] = 0
	for i in range(n - 1):
		if weight.get(fr[i], -1) != -1:
			print(weight[fr[i]])
		elif weight.get(to[i], -1) != -1:
			print(weight[to[i]])
		else:
			print(k)
			k += 1


import sys
import math
import heapq
import collections

def inputnum():
	return int(input())

def inputnums():
	return map(int, input().split())

def inputlist():
	return list(map(int, input().split()))

def inputstring():
	return [x for x in input()]

def inputmatrixchar(rows):
	arr2d = [[j for j in input().strip()] for i in range(rows)]
	return arr2d

def inputmatrixint(rows):
	arr2d = []
	for _ in range(rows):
		arr2d.append([int(i) for i in input().split()])
	return arr2d
n = inputnum()
a = [0] * (n + 1)
us = []
vs = []
ans = [-1] * (n - 1)
for i in range(n - 1):
	(u, v) = inputnums()
	us.append(u)
	vs.append(v)
	a[u] += 1
	a[v] += 1
for i in range(n - 1):
	if a[vs[i]] == 1 or a[us[i]] == 1:
		vs[i] = -1
		us[i] = -1
cur = 0
for i in range(n - 1):
	if vs[i] == -1 or us[i] == -1:
		ans[i] = cur
		cur += 1
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = cur
		cur += 1
	print(ans[i])


from collections import Counter
vertexes_number = int(input())
edges = Counter()
ledger = []
for _ in range(vertexes_number - 1):
	(_from, to) = map(int, input().split())
	ledger.append((_from, to))
	edges[_from] += 1
	edges[to] += 1
((vertex, power),) = edges.most_common(1)
if power >= 3:
	asc_index = 0
	desc_index = vertexes_number - 2
	for (index, (_from, to)) in enumerate(ledger):
		if _from == vertex or to == vertex:
			print(asc_index)
			asc_index += 1
		else:
			print(desc_index)
			desc_index -= 1
else:
	for index in range(len(ledger)):
		print(index)


n = int(input())
check = [0 for i in range(n + 1)]
nodes = []
for i in range(n - 1):
	(u, v) = map(int, input().split())
	nodes.append((u, v))
	check[u] += 1
	check[v] += 1
left = 0
right = n - 2
for (u, v) in nodes:
	if check[u] == 1 or check[v] == 1:
		print(left)
		left += 1
	else:
		print(right)
		right -= 1


t = int(input())
lis1 = []
lis2 = []
for _ in range(t - 1):
	temp = list(input().split(' '))
	lis1.append(int(temp[0]))
	lis2.append(int(temp[1]))
temp = []
temp += lis1 + lis2
temp.sort()
ullist = []
if temp[0] != temp[1]:
	ullist.append(temp[0])
len1 = len(temp)
for i in range(1, len1 - 1):
	if temp[i] != temp[i - 1] and temp[i] != temp[i + 1]:
		ullist.append(temp[i])
if temp[len(temp) - 1] != temp[len(temp) - 2]:
	ullist.append(temp[len(temp) - 1])
if len(ullist) == 2:
	for i in range(t - 1):
		print(i)
else:
	temp2 = [-1] * (t - 1)
	for i in range(t - 1):
		if lis1[i] == ullist[0] or lis2[i] == ullist[0]:
			temp2[i] = 0
		if lis1[i] == ullist[1] or lis2[i] == ullist[1]:
			temp2[i] = 1
		if lis1[i] == ullist[2] or lis2[i] == ullist[2]:
			temp2[i] = 2
	l = 3
	for i in range(t - 1):
		if temp2[i] == -1:
			temp2[i] = l
			l += 1
	for i in temp2:
		print(i)


from collections import defaultdict

def f(arr):
	g = defaultdict(list)
	for i in range(len(arr)):
		g[arr[i][0]].append(i)
		g[arr[i][1]].append(i)
	ans = [-1] * len(arr)
	mx = max(g.items(), key=lambda s: len(s[1]))
	c = 0
	for i in mx[1]:
		ans[i] = c
		c += 1
	for i in range(len(ans)):
		if ans[i] == -1:
			ans[i] = c
			c += 1
	return ans
blanck = []
for i in range(int(input()) - 1):
	(p, c) = map(int, input().strip().split())
	blanck.append([p, c])
print(*f(blanck), sep='\n')


import math
from bisect import bisect_left, bisect_right
from sys import stdin, stdout, setrecursionlimit
from collections import Counter
input = lambda : stdin.readline().strip()
print = stdout.write
n = int(input())
graph = [0]
edge = [0]
for i in range(1, n + 1):
	graph.append(0)
	edge.append(0)
for i in range(n - 1):
	(a, b) = map(int, input().split())
	graph[a] += 1
	graph[b] += 1
	edge[a] = i
	edge[b] = i
ans = []
for i in range(n - 1):
	ans.append(-1)
i = 0
for k in range(1, n + 1):
	v = graph[k]
	if v == 1 and i < min(3, n - 1):
		ans[edge[k]] = i
		i += 1
for k in range(len(ans)):
	if ans[k] == -1:
		ans[k] = i
		i += 1
for i in ans:
	print(str(i) + '\n')


import sys
import collections
n = int(sys.stdin.readline())
adj = {}
res = []
for _ in range(n - 1):
	(u, v) = map(int, sys.stdin.readline().split())
	res.append((min(u, v), max(u, v)))
	if adj.get(u) == None:
		adj[u] = [v]
	else:
		adj[u].append(v)
	if adj.get(v) == None:
		adj[v] = [u]
	else:
		adj[v].append(u)
maxx = 0
for j in adj:
	l = len(adj[j])
	if maxx < l:
		maxx = l
		root_node = j
visited = {}
queue = collections.deque([root_node])
visited[root_node] = 1
mex_val = 0
answer = {}
while len(queue) != 0:
	head = queue.popleft()
	for ed in adj[head]:
		if visited.get(ed) == None:
			answer[min(head, ed), max(head, ed)] = mex_val
			mex_val += 1
			visited[ed] = 1
			queue.append(ed)
for item in res:
	sys.stdout.write(str(answer[item]))
	sys.stdout.write('\n')


from sys import stdin, gettrace
if not gettrace():

	def input():
		return next(stdin)[:-1]

def main():
	n = int(input())
	adj = [[] for _ in range(n)]
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		adj[u - 1].append((v - 1, i))
		adj[v - 1].append((u - 1, i))
	next = 0
	res = [-1] * (n - 1)
	for u in range(n):
		if len(adj[u]) == 1 and res[adj[u][0][1]] == -1:
			res[adj[u][0][1]] = next
			next += 1
			if next == 3:
				break
	for i in range(n - 1):
		if res[i] == -1:
			res[i] = next
			next += 1
	print('\n'.join(map(str, res)))
main()


import os
import sys
from atexit import register
from io import BytesIO
input = BytesIO(os.read(0, os.fstat(0).st_size)).readline
from collections import defaultdict
n = int(input())
Edges = []
Power = defaultdict(int)
for nn in range(n - 1):
	(u, v) = map(int, input().split())
	Power[u] += 1
	Power[v] += 1
	Edges.append((u, v))
onecount = sum((value == 1 for value in Power.values()))
if onecount == 2:
	for i in range(n - 1):
		print(i)
else:
	left = 0
	right = n - 2
	for (u, v) in Edges:
		if Power[u] == 1 or Power[v] == 1:
			print(left)
			left += 1
		else:
			print(right)
			right -= 1


import sys

def f():
	n = int(sys.stdin.readline())
	g = [list() for _ in range(n + 1)]
	a = [-1] * n
	c = [0] * (n + 1)
	s = 0
	for i in range(n - 1):
		(u, v) = map(int, sys.stdin.readline().split())
		g[u].append(i + 1)
		g[v].append(i + 1)
		c[u] += 1
		c[v] += 1
		if c[u] >= 3:
			s = u
		if c[v] >= 3:
			s = v
	g1(n, a, g, c, s)

def g1(n, a, g, c, s):
	if s == 0:
		for i in range(n - 1):
			print(i)
	else:
		for i in range(0, 3):
			a[g[s][i]] = i
		v = 3
		for i in range(1, n):
			if a[i] == -1:
				a[i] = v
				v += 1
			print(a[i])
f()


n = int(input())
if n == 2:
	print(0)
	raise SystemExit
arr = [None for _ in range(n)]
for i in range(n - 1):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	if arr[a] == None:
		arr[a] = i
	else:
		arr[a] = False
	if arr[b] == None:
		arr[b] = i
	else:
		arr[b] = False
ret = [-1 for _ in range(n - 1)]
i = 0
for e in arr:
	if type(e) == int:
		ret[e] = i
		i += 1
for j in range(n - 1):
	if ret[j] == -1:
		ret[j] = i
		i += 1
print('\n'.join(map(str, ret)))


import os
import sys
from io import BytesIO, IOBase
from collections import defaultdict

def solution(tree, edges, n):
	if not any((len(nodes) > 2 for (root, nodes) in tree.items())):
		for i in range(n - 1):
			write(i)
		return
	res = defaultdict(int)
	for (root, nodes) in tree.items():
		if len(nodes) >= 3:
			res[root, nodes[0]] = 0
			res[root, nodes[1]] = 1
			res[root, nodes[2]] = 2
			break
	val = 3
	for edge in edges:
		if edge in res:
			write(res[edge])
		elif edge[::-1] in res:
			write(res[edge[::-1]])
		else:
			write(val)
			val += 1

def main():
	(tree, edges) = (defaultdict(list), [])
	n = r_int()
	for _ in range(n - 1):
		(a, b) = r_array()
		tree[a].append(b)
		tree[b].append(a)
		edges.append((a, b))
	solution(tree, edges, n)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))

def input():
	return sys.stdin.readline().rstrip('\r\n')

def write(*args, end='\n'):
	for x in args:
		sys.stdout.write(str(x) + ' ')
	sys.stdout.write(end)

def r_array():
	return [int(x) for x in input().split()]

def r_int():
	return int(input())

def p_array(arr):
	for x in arr:
		write(x, end=' ')
	write()
main()


from collections import Counter, OrderedDict
from collections import deque
from sys import stdin
from bisect import *
from heapq import *
import math
g = lambda : stdin.readline().strip()
gl = lambda : g().split()
gil = lambda : [int(var) for var in gl()]
gfl = lambda : [float(var) for var in gl()]
gcl = lambda : list(g())
gbs = lambda : [int(var) for var in g()]
mod = int(1000000000.0) + 7
inf = float('inf')
(n,) = gil()
edges = OrderedDict()
adj = [[] for _ in range(n + 1)]
for _ in range(n - 1):
	(x, y) = gil()
	edges[x, y] = None
	edges[y, x] = None
	adj[x].append(y)
	adj[y].append(x)
dp = [1] * (n + 1)
vis = [0] * (n + 1)
fin = [0] * (n + 1)
stack = [1]
while stack:
	node = stack[-1]
	if vis[node]:
		for c in adj[node]:
			if fin[c]:
				dp[node] += dp[c]
		fin[node] = 1
		stack.pop()
	else:
		vis[node] = 1
		for c in adj[node]:
			if vis[c] == 0:
				stack.append(c)
vis = [0] * (n + 1)
stack = [1]
costs = []
while stack:
	node = stack.pop()
	vis[node] = 1
	for c in adj[node]:
		if vis[c] == 0:
			stack.append(c)
			costs.append((dp[c] * (n - dp[c]), node, c))
costs.sort(key=lambda x: x[0], reverse=True)
val = n - 2
for (_, x, y) in costs:
	edges[x, y] = val
	val -= 1
for val in edges.values():
	if val is not None:
		print(val)


from sys import stdin
n = int(stdin.readline())
link_dic = {}
link_list = []
link_time = [0 for i in range(n)]
for i in range(n - 1):
	(x, y) = map(int, stdin.readline().split())
	link_time[x - 1] += 1
	link_time[y - 1] += 1
	link_list.append([x, y])
spe_index = 0
ord_index = n - 2
for (x, y) in link_list:
	if link_time[x - 1] == 1 or link_time[y - 1] == 1:
		print(spe_index)
		spe_index += 1
	else:
		print(ord_index)
		ord_index -= 1


import math
import fractions

def make_divisors(n):
	divisors = []
	for i in range(1, int(n ** 0.5) + 1):
		if n % i == 0:
			divisors.append(i)
			if i != n // i:
				divisors.append(n // i)
	return divisors

def ValueToBits(x, digit):
	res = [0 for i in range(digit)]
	now = x
	for i in range(digit):
		res[i] = now % 2
		now = now >> 1
	return res

def BitsToValue(arr):
	n = len(arr)
	ans = 0
	for i in range(n):
		ans += arr[i] * 2 ** i
	return ans

def ValueToArray10(x, digit):
	ans = [0 for i in range(digit)]
	now = x
	for i in range(digit):
		ans[digit - i - 1] = now % 10
		now = now // 10
	return ans
n = int(input())
nb = [[] for i in range(n)]
nbe = [[] for i in range(n)]
es = []
for i in range(n - 1):
	(a, b) = list(map(int, input().split()))
	a -= 1
	b -= 1
	es.append([a, b])
	nb[a].append(b)
	nb[b].append(a)
	nbe[a].append(i)
	nbe[b].append(i)
start = -1
for i in range(n):
	if len(nb[i]) == 1:
		start = i
		break
queue = [start]
done = 0
checked = [0 for i in range(n)]
checked[start] = 1
u = -1
v = -1
w = -1
while True:
	if len(queue) == done:
		break
	else:
		now = queue[done]
		nownb = nb[now]
		if len(nownb) <= 2:
			for j in range(len(nownb)):
				if checked[nownb[j]] == 0:
					queue.append(nownb[j])
					checked[nownb[j]] = 1
			done += 1
		else:
			u = nbe[now][0]
			v = nbe[now][1]
			w = nbe[now][2]
			break
ans = [0 for i in range(n - 1)]
now = 3
if u != -1:
	for i in range(n - 1):
		if i == u:
			print(0)
		elif i == v:
			print(1)
		elif i == w:
			print(2)
		else:
			print(now)
			now += 1
else:
	for i in range(n - 1):
		print(i)


from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc
import math
from bisect import bisect_left, bisect_right
from sys import stdin, stdout, setrecursionlimit
from collections import Counter
input = lambda : stdin.readline().strip()
import heapq
n = int(input())
degree = [0 for i in range(n + 1)]
adj = [[] for i in range(n + 1)]
ans = [-1 for i in range(n + 1)]
edges = [[] for i in range(n + 1)]
vis_nodes = [False for i in range(n + 1)]
vis_edges = [False for i in range(n + 1)]
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	adj[u].append(v)
	adj[v].append(u)
	degree[u] += 1
	degree[v] += 1
	edges[u].append(_ + 1)
	edges[v].append(_ + 1)
node = [(-1 * degree[i], i) for i in range(1, n + 1)]
heapq.heapify(node)
cnt = 0
while cnt < n - 1 and len(node) > 0:
	k = heapq.heappop(node)
	x = k[1]
	for i in edges[x]:
		if ans[i] == -1:
			ans[i] = cnt
			cnt += 1
for i in range(1, n):
	print(str(ans[i]))


from collections import defaultdict
n = int(input().strip())
p = defaultdict(int)
tt = [0] * ((n - 1) * 2)
for i in range(n - 1):
	(x, y) = map(int, input().strip().split())
	tt[i * 2 + 0] = x
	tt[i * 2 + 1] = y
	p[x] += 1
	p[y] += 1
cnt = 0
ans = [-1] * (n - 1)
for i in range(n - 1):
	if p[tt[i * 2 + 0]] == 1 or p[tt[i * 2 + 1]] == 1:
		ans[i] = cnt
		cnt += 1
for i in range(n - 1):
	if ans[i] != -1:
		print(ans[i])
	else:
		print(cnt)
		cnt += 1


import sys

def input():
	return sys.stdin.readline()[:-1]
n = int(input())
adj = [[] for _ in range(n)]
for i in range(n - 1):
	(u, v) = map(int, input().split())
	adj[u - 1].append((v - 1, i))
	adj[v - 1].append((u - 1, i))
if max([len(x) for x in adj]) <= 2:
	print(*list(range(n - 1)), sep='\n')
else:
	ans = [-1 for _ in range(n - 1)]
	for i in range(n):
		if len(adj[i]) > 2:
			ans[adj[i][0][1]] = 0
			ans[adj[i][1][1]] = 1
			ans[adj[i][2][1]] = 2
			break
	tmp = 3
	for i in range(n - 1):
		if ans[i] < 0:
			ans[i] = tmp
			tmp += 1
	print(*ans, sep='\n')


MOD = 1000000007
MOD2 = 998244353
ii = lambda : int(input())
si = lambda : input()
dgl = lambda : list(map(int, input()))
f = lambda : map(int, input().split())
il = lambda : list(map(int, input().split()))
ls = lambda : list(input())
let = '@abcdefghijklmnopqrstuvwxyz'
n = ii()
deg = [0] * (10 ** 5 + 10)
l = []
(it1, it2) = (0, n - 2)
for _ in range(n - 1):
	(x, y) = f()
	deg[x] += 1
	deg[y] += 1
	l.append([x, y])
for i in l:
	if deg[i[0]] == 1 or deg[i[1]] == 1:
		print(it1)
		it1 += 1
	else:
		print(it2)
		it2 -= 1


import sys
from types import GeneratorType
input = sys.stdin.readline

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc
n = int(input())

class Graph:

	def __init__(self, V):
		self.V = V
		self.adj = [[] for i in range(V)]

	@bootstrap
	def DFSUtil(self, temp, v, visited, edges, parent, l, r):
		visited[v] = True
		temp.append(v)
		count = 0
		for i in self.adj[v]:
			if visited[i] == False:
				temp = (yield self.DFSUtil(temp, i, visited, edges, v, l, r))
				count += 1
		if count == 0:
			edges[v, parent] = l[0]
			l[0] += 1
		else:
			edges[v, parent] = r[0]
			r[0] -= 1
		yield temp

	def addEdge(self, v, w):
		self.adj[v].append(w)
		self.adj[w].append(v)
G = Graph(n)
all_edges = []
for _ in range(n - 1):
	(u, v) = list(map(int, input().split()))
	u -= 1
	v -= 1
	G.addEdge(u, v)
	all_edges.append((u, v))
l = [0]
r = [n - 2]
visited = [False] * n
edges = {}
G.DFSUtil([], 0, visited, edges, -1, l, r)
for i in range(0, len(all_edges)):
	if all_edges[i] in edges:
		print(edges[all_edges[i]])
	else:
		print(edges[all_edges[i][1], all_edges[i][0]])


def solve(n, queries):
	node = 0
	count = [0] * (n + 1)
	for (u, v) in queries:
		count[u] += 1
		count[v] += 1
		if count[u] == 3:
			node = u
		if count[v] == 3:
			node = v
	j = 0
	ans = [-1] * len(queries)
	for (i, pair) in enumerate(queries):
		if node in pair:
			ans[i] = j
			j += 1
	for i in range(len(queries)):
		if ans[i] != -1:
			continue
		ans[i] = j
		j += 1
	for i in ans:
		print(i)

def smain():
	inp = lambda : [int(x) for x in input().split()]
	n = int(input())
	queries = [inp() for _ in range(n - 1)]
	solve(n, queries)
smain()


from sys import stdin
from bisect import bisect_left as bl
from bisect import bisect_right as br

def input():
	return stdin.readline()[:-1]

def intput():
	return int(input())

def sinput():
	return input().split()

def intsput():
	return map(int, sinput())

class RangedList:

	def __init__(self, start, stop, val=0):
		self.shift = 0 - start
		self.start = start
		self.stop = stop
		self.list = [val] * (stop - start)

	def __setitem__(self, key, value):
		self.list[key + self.shift] = value

	def __getitem__(self, key):
		return self.list[key + self.shift]

	def __repr__(self):
		return str(self.list)

	def __iter__(self):
		return iter(self.list)

def dprint(*args, **kwargs):
	if debugging:
		print(*args, **kwargs)
debugging = 1
n = intput()
matrix = {}
for i in range(1, n + 1):
	matrix[i] = []
conns = []
for _ in range(n - 1):
	(u, v) = intsput()
	matrix[u].append(v)
	matrix[v].append(u)
	conns.append([u, v])
leafcnt = 0
leaves = []
for i in range(1, n + 1):
	if len(matrix[i]) == 1:
		leaves.append(i)
		leafcnt += 1
if leafcnt >= 3:
	counter = 3
	for conn in conns:
		if leaves[0] in conn:
			print(0)
		elif leaves[1] in conn:
			print(1)
		elif leaves[2] in conn:
			print(2)
		else:
			print(counter)
			counter += 1
else:
	for i in range(len(conns)):
		print(i)


def listint():
	a = input().split()
	for i in range(len(a)):
		a[i] = int(a[i]) - 1
	return a

def main():
	n = int(input())
	graph = []
	for i in range(n - 1):
		graph.append(listint())
	nodes = []
	for i in range(n):
		nodes.append(0)
	for i in range(n - 1):
		nodes[graph[i][0]] = nodes[graph[i][0]] + 1
		nodes[graph[i][1]] = nodes[graph[i][1]] + 1
	ans = []
	for i in range(n - 1):
		ans.append(-1)
	for i in range(n):
		if nodes[i] >= 3:
			p = 0
			for j in range(n - 1):
				if graph[j][0] == i:
					ans[j] = p
					p = p + 1
				if graph[j][1] == i:
					ans[j] = p
					p = p + 1
			for j in range(n - 1):
				if ans[j] == -1:
					ans[j] = p
					p = p + 1
			return ans
	for i in range(n - 1):
		ans[i] = i
	return ans
ans = main()
for i in range(len(ans)):
	print(ans[i])


import sys
input = sys.stdin.readline
n = int(input())
L = [[] for i in range(n)]
M = dict()
for i in range(n - 1):
	(a, b) = map(int, input().split())
	M[i] = (a, b)
	L[a - 1].append(b)
	L[b - 1].append(a)
mxnode = -1
mxdeg = 0
for j in range(n):
	if len(L[j]) > mxdeg:
		mxdeg = len(L[j])
		mxnode = j + 1
mxpt = 0
normpt = 0
mxedge = list(range(mxdeg))
noredg = list(range(mxdeg, n))
for j in range(n - 1):
	if mxnode in M[j]:
		print(mxedge[mxpt])
		mxpt += 1
	else:
		print(noredg[normpt])
		normpt += 1


import sys
input = lambda : sys.stdin.readline().rstrip()
n = int(input())
edge = []
D = [0] * n
for i in range(n - 1):
	(u, v) = map(int, input().split())
	edge.append((u, v))
	D[u - 1] += 1
	D[v - 1] += 1
if max(D) <= 2:
	for i in range(n - 1):
		print(i)
else:
	Ans = [-1] * (n - 1)
	for i in range(n):
		if D[i] >= 3:
			c = i
			break
	rest = 3
	for i in range(n - 1):
		(u, v) = edge[i]
		if rest:
			if u - 1 == c or v - 1 == c:
				Ans[i] = rest - 1
				rest -= 1
	cur = 3
	for i in range(n - 1):
		if Ans[i] != -1:
			print(Ans[i])
		else:
			print(cur)
			cur += 1


def main():
	data = input().rstrip().split()
	n = int(data[0])
	edges = []
	g = list(([] for _ in range(n)))
	leafes = list((False for _ in range(n)))
	counter = 0
	for _ in range(n - 1):
		(a, b) = sorted(map(int, input().split()))
		(a, b) = (a - 1, b - 1)
		edges.append((a, b))
		g[a].append(b)
		g[b].append(a)
	for (k, v) in enumerate(g):
		if counter == 3:
			break
		if len(v) == 1:
			leafes[k] = True
			counter += 1
	l_counter = 0
	to_print = []
	for edge in edges:
		(a, b) = edge
		if leafes[a] or leafes[b]:
			to_print.append(l_counter)
			l_counter += 1
		else:
			to_print.append(counter)
			counter += 1
	print('\n'.join((str(foo) for foo in to_print)))
main()


n = int(input())
edge = [[] for i in range(n + 1)]
matrix = []
for i in range(n - 1):
	(u, v) = list(map(int, input().split()))
	edge[u].append(v)
	edge[v].append(u)
	matrix.append([u, v])
lis = []
for i in range(1, n + 1):
	lis.append(len(edge[i]))
a = max(lis)
if a <= 2:
	for i in range(n - 1):
		print(i)
else:
	b = lis.index(a)
	arr = []
	for i in range(3):
		arr.append(edge[b + 1][i])
	ans = [-1] * (n - 1)
	p = 0
	for i in range(n - 1):
		if (matrix[i] == [b + 1, arr[0]] or matrix[i] == [arr[0], b + 1]) or (matrix[i] == [b + 1, arr[1]] or matrix[i] == [arr[1], b + 1]) or (matrix[i] == [b + 1, arr[2]] or matrix[i] == [arr[2], b + 1]):
			ans[i] = p
			p += 1
	p = 3
	for i in range(n - 1):
		if ans[i] == -1:
			ans[i] = p
			p += 1
	for i in range(n - 1):
		print(ans[i])


import sys
n = int(input())
a = []
b = dict()
num = False
reader = (line.split() for line in sys.stdin)
for i in range(n - 1):
	a.append(next(reader))
for i in range(n - 1):
	if a[i][0] in b:
		b[a[i][0]] += 1
	else:
		b[a[i][0]] = 1
	if a[i][1] in b:
		b[a[i][1]] += 1
	else:
		b[a[i][1]] = 1
	if b[a[i][1]] == 3:
		num = a[i][1]
		break
	if b[a[i][0]] == 3:
		num = a[i][0]
		break
count = 0
count2 = 3
if not num:
	for i in range(n - 1):
		print(count)
		count += 1
else:
	for i in range(n - 1):
		if num in a[i] and count < 3:
			print(count)
			count += 1
		else:
			print(count2)
			count2 += 1


from sys import stdin
input = lambda : stdin.readline().strip()
from math import ceil, sqrt, factorial, gcd

def solve():
	a = 0
	b = n - 2
	for i in l:
		if len(dx[i[0]]) == 1 or len(dx[i[1]]) == 1:
			print(a)
			a += 1
		else:
			print(b)
			b -= 1
n = int(input())
dx = {i: set() for i in range(1, n + 1)}
d = {i: set() for i in range(1, n + 1)}
l = []
for i in range(n - 1):
	(a, b) = map(int, input().split())
	dx[a].add(b)
	dx[b].add(a)
	l.append([a, b])
solve()


import sys
input = sys.stdin.readline
n = int(input())
from collections import defaultdict
deg = defaultdict(int)
uvl = []
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	uvl.append((u - 1, v - 1))
	deg[u - 1] += 1
	deg[v - 1] += 1
nidx = 0
ansl = [-1 for i in range(n - 1)]
for (idx, (u, v)) in enumerate(uvl):
	if deg[u] == 1 or deg[v] == 1:
		ansl[idx] = nidx
		nidx += 1
for i in range(n - 1):
	if ansl[i] == -1:
		ansl[i] = nidx
		nidx += 1
for a in ansl:
	print(a)


import sys
sys.setrecursionlimit(200000)
LI = lambda : list(map(int, sys.stdin.readline().strip('\n').split()))
MI = lambda : map(int, sys.stdin.readline().strip('\n').split())
SI = lambda : sys.stdin.readline().strip('\n')
II = lambda : int(sys.stdin.readline().strip('\n'))
n = II()
tree = {i: [] for i in range(n + 1)}
vis = [False] * (n + 1)
edges = []
mex = {}
m = 0
for __ in range(n - 1):
	(u, v) = MI()
	edges.append([u, v])
	tree[u].append(v)
	tree[v].append(u)
s = sorted(tree, key=lambda c: len(tree[c]), reverse=True)
for u in s[:-1]:
	for v in tree[u]:
		if mex.get((u, v), -1) == -1 or mex.get((v, u), -1) == -1:
			mex[u, v] = mex[v, u] = m
			m += 1
for (u, v) in edges:
	print(mex[u, v])


from collections import defaultdict
from operator import itemgetter
import sys
input = sys.stdin.readline

def solve(n):
	n_edge = [0] * (n + 1)
	edges = []
	for i in range(n - 1):
		(a, b) = map(int, input().split())
		n_edge[a] += 1
		n_edge[b] += 1
		edges.append((a, b))
	if n <= 3:
		for j in range(0, n - 1):
			print(j)
	else:
		x = list(enumerate(n_edge))[1:]
		y = list(filter(lambda i: i[1] == 1, x))[:3]
		z = set(map(itemgetter(0), y))
		l = len(y)
		cnt1 = 0
		cnt2 = l
		for i in range(1, n):
			if cnt1 < l and (edges[i - 1][0] in z or edges[i - 1][1] in z):
				print(cnt1)
				cnt1 += 1
			else:
				print(cnt2)
				cnt2 += 1

def main():
	n = int(input())
	solve(n)
main()


vertices = int(input())
contador_adjacentes = [0] * (vertices + 1)
grafo = []
for i in range(vertices - 1):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	contador_adjacentes[a] += 1
	contador_adjacentes[b] += 1
	grafo.append([a, b])
contador = 0
mex = vertices - 2
for (a, b) in grafo:
	if contador_adjacentes[a] == 1 or contador_adjacentes[b] == 1:
		print(contador)
		contador += 1
	else:
		print(mex)
		mex -= 1


from sys import stdin
n = int(input())
node = [[] for i in range(n + 1)]
x = []
m = dict()
for i in range(n - 1):
	(a, b) = map(int, stdin.readline().split())
	x.append([a, b])
	m[a, b] = m[b, a] = -1
	node[a].append(b)
	node[b].append(a)
num = 3
for i in range(1, n + 1):
	if len(node[i]) >= 3:
		for i2 in range(3):
			m[node[i][i2], i] = m[i, node[i][i2]] = i2
		break
	if i == n:
		num = 0
for i in range(n - 1):
	if m[x[i][0], x[i][1]] >= 0:
		print(m[x[i][0], x[i][1]])
	else:
		print(num)
		num += 1


class Solution:

	def solve(self, n, queries):
		count = [0] * (n + 1)
		node = 0
		for (u, v) in queries:
			count[u] += 1
			count[v] += 1
			if count[u] == 3:
				node = u
			if count[v] == 3:
				node = v
		ret = []
		i = 0
		j = 3 if node else 0
		for (u, v) in queries:
			if (u == node or v == node) and i < 3:
				ret.append(i)
				i += 1
			else:
				ret.append(j)
				j += 1
		return ret

def main():
	inp = lambda : [int(x) for x in input().split()]
	n = int(input())
	queries = [inp() for _ in range(n - 1)]
	ans = Solution().solve(n, queries)
	for a in ans:
		print(a)
main()


nodes = {}
numNodes = int(input())
nodes = {}
mentioned = {}
for i in range(1, numNodes + 1):
	nodes[i] = set()
	mentioned[i] = []
for _ in range(numNodes - 1):
	edge = input().split(' ')
	mentioned[int(edge[0])].append(_)
	mentioned[int(edge[1])].append(_)
	nodes[int(edge[0])].add(int(edge[1]))
	nodes[int(edge[1])].add(int(edge[0]))
triplet = -1
for i in range(1, numNodes + 1):
	if len(mentioned[i]) >= 3:
		triplet = mentioned[i][:3]
count = 3
tripCount = 0
if triplet == -1:
	for i in range(numNodes - 1):
		print(i)
else:
	for i in range(numNodes - 1):
		if i not in triplet:
			print(count)
			count += 1
		else:
			print(tripCount)
			tripCount += 1


import sys
import heapq
n = int(input())
edges = {}
nodes = {}
label = {}
heap = []
orig = []
for line in sys.stdin.readlines():
	(u, v) = list(map(int, line.split()))
	orig.append((u, v))
	if u in edges:
		edges[u].append(v)
	else:
		edges[u] = [v]
		nodes[u] = 1
	if v in edges:
		edges[v].append(u)
	else:
		edges[v] = [u]
		nodes[v] = 1
for n in nodes:
	heap.append((len(edges[n]), n))
heapq.heapify(heap)
counter = 0
while len(heap) > 0:
	vals = heapq.heappop(heap)
	for e in edges[vals[1]]:
		if (vals[1], e) in label or (e, vals[1]) in label:
			continue
		label[vals[1], e] = counter
		label[e, vals[1]] = counter
		counter += 1
for v in orig:
	print(label[v])


import sys

def input():
	return sys.stdin.readline()

def iinput():
	return int(input())

def rinput():
	return input().split()

def rlinput():
	return [int(i) for i in input().split()]

def main():
	n = iinput()
	w = []
	q = [[] for i in range(n)]
	for i in range(n - 1):
		(u, v) = rlinput()
		q[u - 1].append(i)
		q[v - 1].append(i)
	for i in range(n):
		if len(q[i]) == 1:
			w.append(i)
	if len(w) < 3:
		for i in range(n - 1):
			print(i)
	else:
		o = 3
		for i in range(n - 1):
			if i == q[w[0]][0]:
				print(0)
			elif i == q[w[1]][0]:
				print(1)
			elif i == q[w[2]][0]:
				print(2)
			else:
				print(o)
				o += 1
for i in range(1):
	main()


import sys
readline = sys.stdin.readline

def i1():
	return int(readline())

def nl():
	return [int(s) for s in readline().split()]

def nn(n):
	return [int(readline()) for i in range(n)]

def nnp(n, x):
	return [int(readline()) + x for i in range(n)]

def nmp(n, x):
	return (int(readline()) + x for i in range(n))

def nlp(x):
	return [int(s) + x for s in readline().split()]

def nll(n):
	return [[int(s) for s in readline().split()] for i in range(n)]

def mll(n):
	return ([int(s) for s in readline().split()] for i in range(n))

def s1():
	return readline().rstrip()

def sl():
	return [s for s in readline().split()]

def sn(n):
	return [readline().rstrip() for i in range(n)]

def sm(n):
	return (readline().rstrip() for i in range(n))

def redir(s):
	global readline
	import os
	fn = sys.argv[0] + f'/../in-{s}.txt'
	readline = open(fn).readline if os.path.exists(fn) else readline
import os
if 'DEPTH' in os.environ:

	def printd(*a, **aa):
		print(*a, **aa)
else:

	def printd(*a, **aa):
		pass
redir('c')
n = i1()
edges = [nlp(-1) for i in range(n - 1)]
printd('edges', edges)
degree = [0] * n
for (u, v) in edges:
	degree[u] += 1
	degree[v] += 1
leafs = [i for i in range(n) if degree[i] == 1]
printd(leafs)
labels = list(range(n - 1))
h3 = set(leafs[:3])
lst = set()
for (i, (u, v)) in enumerate(edges):
	if u in h3 or v in h3:
		lst.add(i)
h3 = lst
k = len(h3)
common = set((i for i in h3 if i < k))
printd('h3,common', h3, common)
for (l, r) in zip(set(range(k)) - common, h3 - common):
	printd('l,r', l, r)
	(labels[l], labels[r]) = (r, l)
print('\n'.join((str(i) for i in labels)))


import os
import sys
from io import BytesIO, IOBase
import threading
from collections import Counter
mod = 998244353

def main():
	for _ in range(1):
		n = int(input())
		graph = [[] for i in range(n)]
		edges = []
		for i in range(n - 1):
			(u, v) = map(int, input().split())
			u -= 1
			v -= 1
			edges.append((u, v))
			graph[u].append(v)
			graph[v].append(u)
		i = 0
		while i < n and len(graph[i]) < 3:
			i += 1
		c = 3 if i != n else 0
		k = 0
		node = i
		label = [-1] * (n - 1)
		for i in range(n - 1):
			(u, v) = edges[i]
			if k <= 2 and (u == node or v == node):
				label[i] = k
				k += 1
			else:
				label[i] = c
				c += 1
		for li in label:
			print(li)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


n = int(input())
t = []
yy = False
hh = 0
C = [0] * (n + 1)
for i in range(n - 1):
	(a, b) = map(int, input().split())
	t.append((a, b))
	C[a] += 1
	C[b] += 1
	if not yy:
		if C[a] > 2:
			hh = a
			yy = True
		if C[b] > 2:
			hh = b
			yy = True
if not yy:
	for i in range(0, n - 1):
		print(i)
else:
	a1 = 0
	a2 = 3
	for i in range(n - 1):
		if t[i][0] != hh and t[i][1] != hh:
			print(a2)
			a2 += 1
		else:
			print(a1)
			a1 += 1
			if a1 > 2:
				hh = -1


n = int(input())
edges = []
degree = [0] * n
ans = []
now = 0
x = -1
for i in range(n - 1):
	edges.append(list(map(lambda x: int(x) - 1, input().split(' '))))
	degree[edges[i][0]] += 1
	degree[edges[i][1]] += 1
for i in range(n):
	if degree[i] >= 3:
		x = i
if x == -1:
	for i in range(n - 1):
		print(i)
	exit()
for i in range(n - 1):
	if edges[i][0] == x or edges[i][1] == x:
		ans.append(now)
		now += 1
	else:
		ans.append(-1)
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = now
		now += 1
for i in range(n - 1):
	print(ans[i])


import sys
input = sys.stdin.readline
n = int(input())
verts = [-1] * n
for e in range(n - 1):
	(a, b) = map(int, input().split())
	for v in (a - 1, b - 1):
		if verts[v] == -1:
			verts[v] = e
		else:
			verts[v] = -2
good = set()
for e in verts:
	if e > -1:
		good.add(e)
out = []
smol = 0
tol = 0
for e in range(n - 1):
	if e in good:
		tol += 1
for e in range(n - 1):
	if e in good:
		out.append(smol)
		smol += 1
	else:
		out.append(tol)
		tol += 1
print('\n'.join(map(str, out)))


from sys import stdin, stdout

def input():
	a = stdin.readline()
	if a[-1] == '\n':
		a = a[:-1]
	return a

def print(*argv, end='\n', sep=' '):
	n = len(argv)
	for i in range(n):
		if i == n - 1:
			stdout.write(str(argv[i]))
		else:
			stdout.write(str(argv[i]) + sep)
	stdout.write(end)
mod = 10 ** 9 + 7

def lcm(x, y):
	return x * y / gcd(x, y)

def comb(lst, x):
	return list(c(lst, x))

def fact(x, mod=mod):
	ans = 1
	for i in range(1, x + 1):
		ans = ans * i % mod
	return ans

def arr2D(n, m, default=0):
	lst = []
	for i in range(n):
		temp = [default] * m
		lst.append(temp)
	return lst

def sortDictV(x):
	return {k: v for (k, v) in sorted(x.items(), key=lambda item: item[1])}

def smaller(lst, x):
	return bisect_left(lst, x) - 1

def smallerEq(lst, x):
	return bisect_right(lst, x) - 1

def solve(n, g, lst):
	want = -1
	count = {}
	for i in g:
		if count.get(i) == None:
			count[i] = len(g[i])
		else:
			count[i] += len(g[i])
		for j in g[i]:
			if count.get(j) == None:
				count[j] = 1
			else:
				count[j] += 1
	for i in count:
		if count[i] >= 3:
			want = i
			break
	if want == -1:
		for i in range(n - 1):
			print(i)
	else:
		cnt = 0
		cnt1 = 3
		for i in range(len(lst)):
			if lst[i][0] == want:
				if cnt <= 2:
					print(cnt)
					cnt += 1
				else:
					print(cnt1)
					cnt1 += 1
			elif lst[i][1] == want:
				if cnt <= 2:
					print(cnt)
					cnt += 1
				else:
					print(cnt1)
					cnt1 += 1
			else:
				print(cnt1)
				cnt1 += 1
n = int(input())
g = {}
lst = []
for i in range(n - 1):
	(a, b) = list(map(int, input().split()))
	lst.append([a, b])
	if g.get(a) == None:
		g[a] = [b]
	else:
		g[a].append(b)
solve(n, g, lst)


n = int(input())
edge_count = [0] * 100001
edge_list = []
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	edge_count[u] += 1
	edge_count[v] += 1
	edge_list.append([u, v])
(min_val, max_val) = (0, n - 2)
edge_weight = []
for i in range(len(edge_list)):
	if edge_count[edge_list[i][0]] == 1 or edge_count[edge_list[i][1]] == 1:
		edge_weight.append(min_val)
		min_val += 1
	else:
		edge_weight.append(max_val)
		max_val -= 1
for weight in edge_weight:
	print(weight)


from sys import stdin, stdout
import sys
from collections import Counter
n = int(stdin.readline().strip())
graph = [[] for i in range(n)]
for i in range(n - 1):
	(u, v) = stdin.readline().strip().split(' ')
	(u, v) = (int(u), int(v))
	u -= 1
	v -= 1
	graph[u].append((v, i))
	graph[v].append((u, i))
gino = 0
ans = [-1 for i in range(n - 1)]
graph = sorted(graph, key=lambda x: len(x), reverse=True)
for i in graph:
	for j in i:
		if ans[j[1]] == -1:
			ans[j[1]] = gino
			gino += 1
for i in ans:
	stdout.write(str(i) + '\n')


from sys import stdin
from collections import deque
mod = 10 ** 9 + 7
import sys
import random
from queue import PriorityQueue
from bisect import bisect_right
from bisect import bisect_left
from collections import defaultdict
from math import sqrt, factorial, gcd, log2, inf, ceil
import heapq
input = lambda : sys.stdin.readline().rstrip()
from sys import stdin, stdout
from heapq import heapify, heappush, heappop
from itertools import permutations
from math import factorial as f

def ncr(x, y):
	return f(x) // (f(y) * f(x - y))
n = int(input())
hash = defaultdict(list)
ba = set()
hash1 = defaultdict(int)
for i in range(n - 1):
	(a, b) = map(int, input().split())
	hash1[a, b] = i + 1
	hash1[b, a] = i + 1
	hash[a].append(b)
	hash[b].append(a)
ans = [-1] * (n - 1)
boo = defaultdict(bool)
flag = 0
if n > 3:
	for i in range(n):
		if len(hash[i]) >= 3:
			(a, b, c) = (hash[i][0], hash[i][1], hash[i][2])
			(z1, z2, z3) = (hash1[a, i], hash1[b, i], hash1[c, i])
			ans[z1 - 1] = 0
			ans[z2 - 1] = 1
			ans[z3 - 1] = 2
			flag = 1
			break
else:
	for i in range(n - 1):
		print(i)
	exit()
if flag:
	la = [i for i in range(3, n - 1)]
else:
	la = [i for i in range(n - 1)]
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = la.pop()
for i in ans:
	print(i)


import math, sys, bisect, heapq
from collections import defaultdict, Counter, deque
from itertools import groupby, accumulate
from functools import lru_cache
int1 = lambda x: int(x) - 1
input = iter(sys.stdin.buffer.read().decode().splitlines()).__next__
aj = lambda : list(map(int, input().split()))

def list3d(a, b, c, d):
	return [[[d] * c for j in range(b)] for i in range(a)]

def Y(c):
	print(['NO', 'YES'][c])

def y(c):
	print(['no', 'yes'][c])

def Yy(c):
	print(['No', 'Yes'][c])
G = defaultdict(list)
C = Counter()
order = []

def addEdge(a, b):
	G[a].append(b)
	G[b].append(a)
	C[a] += 1
	C[b] += 1
	order.append((a, b))
(n,) = aj()
for i in range(n - 1):
	(a, b) = aj()
	addEdge(a, b)
E = []
for i in C.keys():
	E.append((C[i], i))
E.sort()
mark = {}
p = 0
for (i, j) in E:
	for l in G[j]:
		if mark.get((j, l), -1) == -1:
			mark[j, l] = p
			mark[l, j] = p
			p += 1
for i in order:
	print(mark[i])


n = int(input())
dic = {}
ar = []
for i in range(1, n + 1):
	dic[i] = 0
for i in range(n - 1):
	(a, b) = map(int, input().split())
	dic[a] += 1
	dic[b] += 1
	ar.append([a, b])
sta = 0
end = n - 2
for (y, z) in ar:
	if dic[y] == 1 or dic[z] == 1:
		print(sta)
		sta += 1
	else:
		print(end)
		end -= 1


N = int(input())
leaves = {}
edges = [0 for i in range(N)]
for edge in range(N - 1):
	(a, b) = list(map(int, input().split()))
	for node in (a, b):
		edges[node - 1] += 1
		if edges[node - 1] == 1:
			leaves[node] = edge
		elif edges[node - 1] == 2:
			del leaves[node]
if len(leaves) < 3:
	for n in range(N - 1):
		print(n)
else:
	start = 3
	leaf = 0
	specials = list(leaves.values())[:3]
	for edge in range(N - 1):
		if edge in specials:
			print(leaf)
			leaf += 1
		else:
			print(start)
			start += 1


n = int(input())
a = [[] for i in range(n + 1)]
b = []
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	a[u].append(v)
	a[v].append(u)
	b.append((u, v))
c = 0
for _ in range(1, n + 1):
	if len(a[_]) == 1:
		c += 1
p = 0
q = c
for i in b:
	if len(a[i[0]]) == 1 or len(a[i[1]]) == 1:
		print(p)
		p += 1
	else:
		print(q)
		q += 1


import sys
from collections import defaultdict
n = int(sys.stdin.readline())
graph = defaultdict(list)
rem = []
for _ in range(n - 1):
	(u, v) = map(int, sys.stdin.readline().split())
	graph[u].append(v)
	graph[v].append(u)
	rem.append([min(u, v), max(u, v)])
l = []
for i in graph:
	l.append([len(graph[i]), i])
l.sort()
vis = defaultdict(lambda : -1)
count = 0
for i in range(len(l) - 1, -1, -1):
	node = l[i][1]
	for j in range(len(graph[node])):
		(a, b) = (min(graph[node][j], node), max(graph[node][j], node))
		if vis[a, b] == -1:
			vis[a, b] = count
			count += 1
for (i, j) in rem:
	print(vis[i, j])


import sys
input = sys.stdin.buffer.readline
n = int(input())
adj = [[] for _ in range(n + 1)]
for edgeNo in range(n - 1):
	(u, v) = [int(x) for x in input().split()]
	adj[u].append([v, edgeNo])
	adj[v].append([u, edgeNo])
allLeafEdges = set()
for node in range(1, n + 1):
	if len(adj[node]) == 1:
		allLeafEdges.add(adj[node][0][1])
allLeafEdges = list(allLeafEdges)
ans = [-1 for __ in range(n - 1)]
if len(allLeafEdges) >= 3:
	ans[allLeafEdges[0]] = 0
	ans[allLeafEdges[1]] = 1
	ans[allLeafEdges[2]] = 2
	idx = 0
	for i in range(3, n - 1):
		while idx < n - 1 and ans[idx] != -1:
			idx += 1
		ans[idx] = i
else:
	ans = list(range(n - 1))
print('\n'.join([str(x) for x in ans]))


import sys

def calcdist(adj_list, visited, stack, d):
	node = stack.pop()
	if visited[node]:
		return
	visited[node] = True
	for e in adj_list[node]:
		if visited[e] == False:
			stack.append(e)
			d[e] = d[node] + 1
	return

def answer(n, u, v):
	if n == 2:
		print(0)
		return
	adj_list = [[] for _ in range(n + 1)]
	for i in range(n - 1):
		adj_list[v[i]].append(u[i])
		adj_list[u[i]].append(v[i])
	leaf = [False for _ in range(n + 1)]
	label = [10 ** 6 for _ in range(n + 1)]
	next_label = 0
	for i in range(1, n + 1):
		if len(adj_list[i]) == 1:
			leaf[i] = True
			label[i] = next_label
			next_label += 1
	root = 0
	for i in range(1, n + 1):
		if leaf[i] == False:
			label[i] = next_label
			next_label += 1
			root = i
	visited = [False for _ in range(n + 1)]
	stack = [root]
	d = [0 for _ in range(n + 1)]
	while len(stack) > 0:
		calcdist(adj_list, visited, stack, d)
	for i in range(n - 1):
		if d[v[i]] > d[u[i]]:
			print(label[v[i]])
		else:
			print(label[u[i]])
	return

def main():
	n = int(sys.stdin.readline())
	u = [0 for i in range(n - 1)]
	v = [0 for i in range(n - 1)]
	for i in range(n - 1):
		(u[i], v[i]) = map(int, sys.stdin.readline().split())
	answer(n, u, v)
	return
main()


import sys
sys.setrecursionlimit(10 ** 6)
int1 = lambda x: int(x) - 1
p2D = lambda x: print(*x, sep='\n')

def II():
	return int(sys.stdin.readline())

def MI():
	return map(int, sys.stdin.readline().split())

def MI1():
	return map(int1, sys.stdin.readline().split())

def LI():
	return list(map(int, sys.stdin.readline().split()))

def LLI(rows_number):
	return [LI() for _ in range(rows_number)]

def SI():
	return sys.stdin.readline()[:-1]

def main():
	n = II()
	to = [[] for _ in range(n)]
	deg = [0] * n
	for i in range(n - 1):
		(u, v) = MI1()
		to[u].append((v, i))
		to[v].append((u, i))
		deg[u] += 1
		deg[v] += 1
	mx = max(deg)
	if mx < 3:
		ans = list(range(n - 1))
	else:
		ans = [-1] * (n - 1)
		u = deg.index(mx)
		c = 0
		for (v, i) in to[u]:
			if c == 3:
				break
			ans[i] = c
			c += 1
		for i in range(n - 1):
			if ans[i] != -1:
				continue
			ans[i] = c
			c += 1
	print(*ans, sep='\n')
main()


import sys
n = int(input())
data = sys.stdin.readlines()
g = [[] for i in range(n)]
ribs = dict()
for i in range(n - 1):
	(v, u) = map(int, data[i].split())
	v -= 1
	u -= 1
	ribs[frozenset([v, u])] = i
	g[v].append(u)
	g[u].append(v)
answer = [-1] * (n - 1)
count = 0
for v in range(n):
	if len(g[v]) == 1 and answer[ribs[frozenset([v, g[v][0]])]] == -1:
		answer[ribs[frozenset([v, g[v][0]])]] = count
		count += 1
for i in range(n - 1):
	if answer[i] == -1:
		answer[i] = count
		count += 1
print(*answer, sep='\n')


def main():
	n = int(input())
	order = []
	tree = {}
	for i in range(1, n + 1):
		tree[i] = []
	edges = {}
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		tree[u].append(v)
		tree[v].append(u)
		order.append((u, v))
	found = False
	for i in tree.keys():
		if len(tree[i]) >= 3:
			found = True
			node = i
			break
	ans = []
	if not found:
		for i in range(n - 1):
			ans.append(i)
	else:
		curr = n - 2
		count = 0
		while order:
			(u, v) = order.pop(0)
			if count < 3:
				if u == node or v == node:
					ans.append(count)
					count += 1
				else:
					ans.append(curr)
					curr -= 1
			else:
				ans.append(curr)
				curr -= 1
	for i in ans:
		print(i)
main()


from __future__ import division, print_function
import os
import sys
from io import BytesIO, IOBase
if sys.version_info[0] < 3:
	from __builtin__ import xrange as range
	from future_builtins import ascii, filter, hex, map, oct, zip

def main():
	n = int(input().strip())
	edges = []
	for _ in range(n - 1):
		edges.append([int(s) - 1 for s in input().strip().split()])
	degrees = [0] * n
	for (u, v) in edges:
		degrees[u] += 1
		degrees[v] += 1
	(lo, hi) = (0, n - 2)
	for (u, v) in edges:
		if degrees[u] == 1 or degrees[v] == 1:
			print(lo)
			lo += 1
		else:
			print(hi)
			hi -= 1
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


import sys
input = sys.stdin.readline
n = int(input())
dg = 10 ** 6
edge = [[] for i in range(n + 1)]
p = []
for i in range(n - 1):
	(u, v) = map(int, input().split())
	edge[u].append(v)
	edge[v].append(u)
	p.append(u * dg + v)
q = -1
for i in range(1, n + 1):
	if len(edge[i]) >= 3:
		q = i
		break
if q == -1:
	for i in range(n - 1):
		print(i)
else:
	X = 0
	mi = 3
	for e in p:
		(a, b) = (e // dg, e % dg)
		if q in (a, b):
			if X != 3:
				print(X)
				X += 1
			else:
				print(mi)
				mi += 1
		else:
			print(mi)
			mi += 1


from sys import stdin, stdout
from math import gcd, sqrt
from collections import deque
input = stdin.readline
R = lambda : map(int, input().split())
I = lambda : int(input())
S = lambda : input().rstrip('\n')
L = lambda : list(R())
P = lambda x: stdout.write(x)
lcm = lambda x, y: x * y // gcd(x, y)
hg = lambda x, y: (y + x - 1) // x * x
pw = lambda x: 1 if x == 1 else 1 + pw(x // 2)
chk = lambda x: chk(x // 2) if not x % 2 else True if x == 1 else False
sm = lambda x: (x ** 2 + x) // 2
N = 10 ** 9 + 7
n = I()
v = [[] for i in range(n)]
val = [0] * n
ln = [0] * n
p = 0
for i in range(n - 1):
	(x, y) = R()
	v[x - 1] += (i,)
	v[y - 1] += (i,)
	ln[x - 1] += 1
	ln[y - 1] += 1
for i in range(n):
	if ln[i] >= 3:
		val[v[i][0]] = 1
		val[v[i][1]] = 2
		val[v[i][2]] = 3
		p = 3
		break
for i in range(n - 1):
	if val[i]:
		print(val[i] - 1)
	else:
		print(p)
		p += 1


import sys
sys.setrecursionlimit(1000000)
input = sys.stdin.readline
n = int(input())
g = [[] for _ in range(n)]
for i in range(n - 1):
	(u, v) = map(int, input().split())
	(u, v) = (u - 1, v - 1)
	g[u].append([v, i])
	g[v].append([u, i])
ans = [-1] * (n - 1)
k = 0
for i in range(n):
	if len(g[i]) >= 3:
		for (u, ei) in g[i]:
			ans[ei] = k
			k += 1
		break
for i in range(n - 1):
	if ans[i] == -1:
		ans[i] = k
		k += 1
for i in range(n - 1):
	print(ans[i])


import sys
input = sys.stdin.readline
print = sys.stdout.write
freqs = [0] * 100001
up_index = 0
down_index = 0

def make_number(edge):
	global down_index
	global up_index
	global freqs
	if freqs[edge[0]] == 1 or freqs[edge[1]] == 1:
		num = down_index
		down_index += 1
		return num
	num = up_index
	up_index += 1
	return num

def solve():
	global freqs
	global up_index
	n = int(input())
	lines = sys.stdin.readlines()
	edges = [tuple(map(int, line.split())) for line in lines]
	for edge in edges:
		freqs[edge[0]] += 1
		freqs[edge[1]] += 1
	down_nodes = [node for node in range(n + 1) if freqs[node] == 1]
	start_up_count = len(down_nodes)
	up_index = start_up_count
	ans = '\n'.join([str(make_number(edge)) for edge in edges])
	print(ans)
solve()


import sys
input = sys.stdin.readline
n = int(input())
e = [tuple(map(int, input().split())) for _ in range(n - 1)]
g = [[] for _ in range(n + 1)]
for (i, (u, v)) in enumerate(e):
	g[u].append((v, i))
	g[v].append((u, i))
r = max(((len(g[u]), u) for u in range(1, n + 1)))[1]
ans = [0] * (n - 1)
nxt = 0
mk = [0] * (n + 1)
mk[r] = 1
q = [r]
while q:
	q2 = []
	for u in q:
		for (v, i) in g[u]:
			if mk[v]:
				continue
			ans[i] = nxt
			nxt += 1
			mk[v] = 1
			q2.append(v)
	q = q2
print(*ans, sep='\n')


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from collections import defaultdict
n = int(input())
v = [0] * (n + 1)
d = defaultdict(int)
a = n - 2
adj = [[] for i in range(n + 1)]
l = []
for i in range(n - 1):
	(x, y) = map(int, input().split())
	l.append((x, y))
	adj[x].append(y)
	adj[y].append(x)
a = 0
(x, y) = (0, 0)
for i in range(1, n + 1):
	if len(adj[i]) >= 3:
		for j in adj[i]:
			if a == 0:
				x = i
				y = j
			d[i, j] = a
			d[j, i] = a
			a += 1
		break
for i in l:
	if d[i] == 0:
		if i != (x, y) and i != (y, x):
			d[i] = a
			a += 1
for i in l:
	print(d[i])


n = int(input())
adj = [[] for _ in range(n)]
edg = []
for i in range(0, n - 1):
	V = list(map(int, input().split()))
	(u, v) = (V[0] - 1, V[1] - 1)
	adj[u].append(v)
	adj[v].append(u)
	edg.append((u, v))
ans = []
for i in range(0, n - 1):
	ans.append(-1)
cnt = 0
for i in range(0, n - 1):
	if (len(adj[edg[i][0]]) == 1 or len(adj[edg[i][1]]) == 1) and cnt < 3:
		ans[i] = cnt
		cnt += 1
for i in range(0, n - 1):
	if ans[i] == -1:
		ans[i] = cnt
		cnt += 1
for i in range(0, n - 1):
	print(ans[i])


n = int(input())
edges = []
degree = [0] * n
for __ in range(n - 1):
	a = [int(x) for x in input().split()]
	edges.append(a)
	degree[a[1] - 1] += 1
	degree[a[0] - 1] += 1
count = n - 2
value = 0
if max(degree) == 1:
	for i in range(n - 1):
		print(i)
else:
	for i in range(n - 1):
		a = edges[i]
		if degree[a[0] - 1] == 1 or degree[a[1] - 1] == 1:
			print(value)
			value += 1
		else:
			print(count)
			count -= 1


n = int(input())
edges = []
neighbs = [0 for i in range(n)]
for i in range(n - 1):
	(u, v) = map(int, input().split())
	edges.append((u, v))
	neighbs[u - 1] += 1
	neighbs[v - 1] += 1
low_next = 0
high_next = n - 2
for (u, v) in edges:
	if neighbs[u - 1] == 1 or neighbs[v - 1] == 1:
		print(low_next)
		low_next += 1
	else:
		print(high_next)
		high_next -= 1


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
n = int(input())
graph = [[] for s in range(n)]
inds = {}
leaf = set([])
for s in range(n - 1):
	(u, v) = map(int, input().split())
	u -= 1
	v -= 1
	inds[u, v] = s
	inds[v, u] = s
	graph[u].append(v)
	graph[v].append(u)
	if len(graph[u]) == 1:
		leaf.add(u)
	elif u in leaf:
		leaf.remove(u)
	if len(graph[v]) == 1:
		leaf.add(v)
	elif v in leaf:
		leaf.remove(v)
ans = [-1 for s in range(n - 1)]
cv = 0
if len(leaf) >= 3:
	while len(leaf) > 0:
		v0 = leaf.pop()
		v1 = graph[v0][0]
		ind = inds[v0, v1]
		ans[ind] = cv
		cv += 1
	for s in range(n - 1):
		if ans[s - 1] == -1:
			ans[s - 1] = cv
			cv += 1
else:
	for s in range(n - 1):
		ans[s] = s
for s in range(n - 1):
	print(ans[s])


import os
from io import BytesIO, IOBase
import sys
from collections import defaultdict, deque, Counter
from bisect import *
import sys

def main():
	n = int(input())
	tree = defaultdict(list)
	b = []
	c = set()
	for i in range(n - 1):
		(x, y) = map(int, input().split())
		tree[x].append(y)
		tree[y].append(x)
		c.add((x, y))
		b.append((x, y))
	d = {}
	e = 0
	for i in tree:
		if len(tree[i]) >= 3:
			for j in tree[i]:
				if (j, i) in c:
					d[j, i] = e
				else:
					d[i, j] = e
				e += 1
				if e == 3:
					break
			break
	for i in b:
		if d.get(i) != None:
			print(d[i])
		else:
			print(e)
			e += 1
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


n = int(input())
dp = [0] * (n + 1)
data = []
for _ in range(n - 1):
	(x, y) = map(int, input().split())
	dp[x - 1] += 1
	dp[y - 1] += 1
	data.append([x - 1, y - 1])
(count, rev) = (0, n - 2)
for (x, y) in data:
	if dp[x] == 1 or dp[y] == 1:
		print(count)
		count += 1
	else:
		print(rev)
		rev -= 1


import math
import sys
from collections import defaultdict, Counter
from itertools import groupby
rt = lambda : map(int, input().split())
ri = lambda : int(input())
rl = lambda : list(map(int, input().split()))

def main():
	n = ri()
	deg = [0] * n
	edges = []
	for _ in range(n - 1):
		(u, v) = rt()
		edges.append((u - 1, v - 1))
		deg[u - 1] += 1
		deg[v - 1] += 1
	if max(deg) <= 2:
		print('\n'.join(map(str, range(n - 1))))
	else:
		d3 = 0
		while deg[d3] < 3:
			d3 += 1
		all = set(range(n - 1))
		res = [-1] * (n - 1)
		index = 0
		for val in range(3):
			while edges[index][0] != d3 and edges[index][1] != d3:
				index += 1
			res[index] = val
			index += 1
			all.remove(val)
		index = 0
		for val in all:
			while res[index] != -1:
				index += 1
			res[index] = val
		print('\n'.join(map(str, res)))
main()


import sys
input = sys.stdin.readline

def li():
	return [int(i) for i in input().rstrip('\n').split()]

def st():
	return input().rstrip('\n')

def val():
	return int(input().rstrip('\n'))

def li2():
	return [i for i in input().rstrip('\n')]

def li3():
	return [int(i) for i in input().rstrip('\n')]
from collections import *
n = val()
g = defaultdict(set)
l = []
ans = [-1 for i in range(n)]
camein = [set() for i in range(n + 10)]
if n == 2:
	print(0)
	exit()
elif n == 3:
	print(0, 1)
	exit()
done = 1
curr = 0
for i in range(n - 1):
	(a, b) = li()
	g[a].add(b)
	g[b].add(a)
	if done:
		camein[a].add(i)
		camein[b].add(i)
		if len(camein[a]) == 3:
			for k in camein[a]:
				ans[k] = curr
				curr += 1
				if curr == 3:
					break
			done = 0
			break
		elif len(camein[b]) == 3:
			for k in camein[b]:
				ans[k] = curr
				curr += 1
				if curr == 3:
					break
			done = 0
			break
for i in range(n - 1):
	if ans[i] != -1:
		print(ans[i])
	else:
		print(curr)
		curr += 1


import atexit
import io
import sys
_INPUT_LINES = sys.stdin.read().splitlines()
input = iter(_INPUT_LINES).__next__
_OUTPUT_BUFFER = io.StringIO()
sys.stdout = _OUTPUT_BUFFER

@atexit.register
def write():
	sys.__stdout__.write(_OUTPUT_BUFFER.getvalue())
import sys

def main():
	data = input().rstrip().split()
	n = int(data[0])
	edges = []
	g = list(([] for _ in range(n)))
	leafes = list((False for _ in range(n)))
	counter = 0
	for _ in range(n - 1):
		(a, b) = sorted(map(int, input().split()))
		(a, b) = (a - 1, b - 1)
		edges.append((a, b))
		g[a].append(b)
		g[b].append(a)
	for (k, v) in enumerate(g):
		if counter == 3:
			break
		if len(v) == 1:
			leafes[k] = True
			counter += 1
	l_counter = 0
	to_print = []
	for edge in edges:
		(a, b) = edge
		if leafes[a] or leafes[b]:
			to_print.append(l_counter)
			l_counter += 1
		else:
			to_print.append(counter)
			counter += 1
	for foo in to_print:
		print(foo)
main()


n = int(input())
jaya = [0] * (n + 1)
l = []
for i in range(n - 1):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	jaya[a] += 1
	jaya[b] += 1
	l.append([a, b])
m = 0
mex = n - 2
for (a, b) in l:
	if jaya[a] == 1 or jaya[b] == 1:
		print(m)
		m += 1
	else:
		print(mex)
		mex -= 1


n = int(input())
graf = dict()
ucka = []
vcka = []
pocty = n * [0]
for i in range(n - 1):
	[u, v] = [int(x) for x in input().split()]
	ucka.append(u)
	vcka.append(v)
	pocty[u - 1] += 1
	pocty[v - 1] += 1
hrana = None
if max(pocty) > 2:
	for i in range(n):
		if pocty[i] > 2:
			hrana = i + 1
			break
spodne = 0
akt = 3
if hrana == None:
	for i in range(n - 1):
		print(i)
else:
	for i in range(n - 1):
		if (ucka[i] == hrana or vcka[i] == hrana) and spodne < 3:
			print(spodne)
			spodne = spodne + 1
		else:
			print(akt)
			akt = akt + 1


n = int(input())
g = [0] * n
edges = []
for i in range(n - 1):
	(u, v) = map(int, input().split())
	g[u - 1] += 1
	g[v - 1] += 1
	edges.append((u - 1, v - 1))
cnt = 0
mex = n - 2
for (a, b) in edges:
	if g[a] == 1 or g[b] == 1:
		print(cnt)
		cnt += 1
	else:
		print(mex)
		mex -= 1


n = int(input())
g = [0] * (n + 1)
l = []
for i in range(n - 1):
	l.append([int(x) for x in input().split()])
	g[l[-1][0] - 1] += 1
	g[l[-1][1] - 1] += 1
(cnt, mex) = (0, n - 2)
for (a, b) in l:
	k = g[a - 1] == 1 or g[b - 1] == 1
	print(cnt if k else mex)
	cnt += int(k)
	mex -= int(not k)


from collections import Counter, defaultdict, deque
from heapq import heapify, heappush, heappop, heappushpop
from sys import stdin
int_inp = lambda : int(stdin.readline().strip())
lst_inp = lambda : [int(i) for i in stdin.readline().strip().split(' ')]
str_inp = lambda : stdin.readline().strip()
n = int_inp()
G = Counter()
edges = []
for _ in range(n - 1):
	(u, v) = lst_inp()
	G[u] += 1
	G[v] += 1
	edges.append((u, v))
for u in G:
	if G[u] >= 3:
		deg_3 = u
		break
else:
	deg_3 = 0
cntr = 0 if deg_3 == 0 else 3
spec = 0
for (u, v) in edges:
	if deg_3 in {u, v}:
		print(spec)
		spec += 1
		if spec >= 3:
			deg_3 = -1
	else:
		print(cntr)
		cntr += 1


import os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
n = int(input())
d = {i: [] for i in range(1, n + 1)}
a = []
for i in range(n - 1):
	(u, v) = list(map(int, input().split()))
	d[u].append(v)
	d[v].append(u)
	a.append((u, v))
c = 0
d1 = {}
for (i, j) in a:
	if len(d[i]) == 1 or len(d[j]) == 1:
		d1[i, j] = c
		c += 1
	if c == 3:
		break
for (i, j) in a:
	if (i, j) not in d1:
		print(c)
		c += 1
	else:
		print(d1[i, j])


import math, string, itertools, fractions, heapq, collections, re, array, bisect, sys, copy, functools
inf = 10 ** 20
eps = 1.0 / 10 ** 10
mod = 10 ** 9 + 7
mod2 = 998244353
dd = [(-1, 0), (0, 1), (1, 0), (0, -1)]
ddn = [(-1, 0), (-1, 1), (0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1)]

def LI():
	return list(map(int, sys.stdin.readline().split()))

def LLI():
	return [list(map(int, l.split())) for l in sys.stdin.readlines()]

def LI_():
	return [int(x) - 1 for x in sys.stdin.readline().split()]

def LF():
	return [float(x) for x in sys.stdin.readline().split()]

def LS():
	return sys.stdin.readline().split()

def I():
	return int(sys.stdin.readline())

def F():
	return float(sys.stdin.readline())

def S():
	return input()

def pf(s):
	return print(s, flush=True)

def pe(s):
	return print(str(s), file=sys.stderr)

def JA(a, sep):
	return sep.join(map(str, a))

def JAA(a, s, t):
	return s.join((t.join(map(str, b)) for b in a))

def IF(c, t, f):
	return t if c else f

def YES(c):
	return IF(c, 'YES', 'NO')

def Yes(c):
	return IF(c, 'Yes', 'No')

def main():
	t = 1
	rr = []
	for _ in range(t):
		n = I()
		a = [LI_() for _ in range(n - 1)]
		d = {}
		e = collections.defaultdict(set)
		for i in range(n - 1):
			(u, v) = a[i]
			e[u].add(v)
			e[v].add(u)
			d[u, v] = d[v, u] = i
		r = [-1] * (n - 1)
		q = []
		for i in range(n):
			if len(e[i]) == 1:
				q.append(i)
		k = 0
		for i in range(n):
			t = q[i]
			for c in e[t]:
				ri = d[t, c]
				if r[ri] >= 0:
					continue
				r[ri] = k
				k += 1
				e[c].remove(t)
				if len(e[c]) == 1:
					q.append(c)
		rr.append(JA(r, '\n'))
	return JA(rr, '\n')
print(main())


n = int(input())
graph = [[] for i in range(n + 1)]
taken = [False for i in range(n - 1)]
xx = []
mp_unit = {}
mp = {}
for i in range(n - 1):
	xg = input()
	xx.append(xg)
	(a, b) = map(int, xg.split())
	graph[a].append(b)
	graph[b].append(a)
	mp[xg] = 1
count = 0
ans = []
for i in range(1, n + 1):
	if len(graph[i]) == 1:
		count += 1
if count <= 2:
	for i in range(n - 1):
		ans.append(i)
else:
	for i in range(1, n + 1):
		if len(graph[i]) == 1:
			branch = str(i) + ' ' + str(graph[i][0])
			b2 = str(graph[i][0]) + ' ' + str(i)
			if branch in mp:
				mp[branch] = 10 ** 7
			else:
				mp[b2] = 10 ** 7
	id = count
	im = 0
	for i in xx:
		if mp[i] != 10 ** 7:
			ans.append(id)
			id += 1
		else:
			ans.append(im)
			im += 1
for i in ans:
	print(i)


from sys import stdin
from collections import defaultdict
import operator
N = int(input())
vertex = defaultdict(lambda : [])
zz = False
edges = []
for _ in range(N - 1):
	(u, v) = map(int, stdin.readline().split())
	vertex[u].append(v)
	vertex[v].append(u)
	edges.append((u, v))
three_node = False
for v in vertex.keys():
	if len(vertex[v]) >= 3:
		three_node = True
		mark = v
if three_node:
	c = 0
	other = 3
	for i in range(N - 1):
		(u, v) = edges[i]
		if mark in (u, v) and c <= 2:
			print(c)
			c += 1
		else:
			print(other)
			other += 1
else:
	for i in range(N - 1):
		print(i)