package main
import (
"bufio"
"fmt"
"os"
)
type Edge struct {
to int
id int
}
var (
n int
adj [][]Edge
U, V []int
sz []int
best int
centroid int
parent []int
parentEdge []int
val []int
weights []int
stepB int
)
func dfsCentroid(v, p int) {
sz[v] = 1
maxPart := 0
for _, e := range adj[v] {
if e.to == p {
continue
}
dfsCentroid(e.to, v)
sz[v] += sz[e.to]
if sz[e.to] > maxPart {
maxPart = sz[e.to]
}
}
if n-sz[v] > maxPart {
maxPart = n - sz[v]
}
if maxPart < best {
best = maxPart
centroid = v
}
}
func dfsRoot(v, p int) {
parent[v] = p
sz[v] = 1
for _, e := range adj[v] {
if e.to == p {
continue
}
parentEdge[e.to] = e.id
dfsRoot(e.to, v)
sz[v] += sz[e.to]
}
}
func assignA(v, p int, counter *int) {
val[v] = *counter
*counter = *counter + 1
weights[parentEdge[v]] = val[v] - val[p]
for _, e := range adj[v] {
if e.to == p {
continue
}
assignA(e.to, v, counter)
}
}
func assignB(v, p int, counter *int) {
val[v] = (*counter) * stepB
*counter = *counter + 1
weights[parentEdge[v]] = val[v] - val[p]
for _, e := range adj[v] {
if e.to == p {
continue
}
assignB(e.to, v, counter)
}
}
func main() {
in := bufio.NewReader(os.Stdin)
fmt.Fscan(in, &n)
if n == 1 {
return
}
adj = make([][]Edge, n+1)
m := n - 1
U = make([]int, m)
V = make([]int, m)
weights = make([]int, m)
for i := 0; i < m; i++ {
fmt.Fscan(in, &U[i], &V[i])
u, v := U[i], V[i]
adj[u] = append(adj[u], Edge{v, i})
adj[v] = append(adj[v], Edge{u, i})
}
sz = make([]int, n+1)
best = n + 1
centroid = 1
dfsCentroid(1, 0)
parent = make([]int, n+1)
parentEdge = make([]int, n+1)
sz = make([]int, n+1)
dfsRoot(centroid, 0)
children := make([]int, 0)
sizes := make([]int, 0)
for _, e := range adj[centroid] {
children = append(children, e.to)
sizes = append(sizes, sz[e.to])
}
k := len(children)
limit := n
prev := make([][]int, k+1)
take := make([][]bool, k+1)
for i := 0; i <= k; i++ {
prev[i] = make([]int, limit+1)
take[i] = make([]bool, limit+1)
for s := 0; s <= limit; s++ {
prev[i][s] = -1
}
}
prev[0][0] = 0
for i := 0; i < k; i++ {
w := sizes[i]
for s := 0; s <= limit; s++ {
if prev[i][s] == -1 {
continue
}
if prev[i+1][s] == -1 {
prev[i+1][s] = s
take[i+1][s] = false
}
if s+w <= limit && prev[i+1][s+w] == -1 {
prev[i+1][s+w] = s
take[i+1][s+w] = true
}
}
}
target := -1
bestCover := -1
for s := 0; s <= n-1; s++ {
if prev[k][s] == -1 {
continue
}
cover := (s + 1) * (n - s) - 1
if cover > bestCover {
bestCover = cover
target = s
}
}
selectedChild := make([]bool, n+1)
cur := target
for i := k; i >= 1; i-- {
if take[i][cur] {
selectedChild[children[i-1]] = true
}
cur = prev[i][cur]
}
a := target + 1
val = make([]int, n+1)
val[centroid] = 0
counterA := 1
for _, child := range children {
if selectedChild[child] {
assignA(child, centroid, &counterA)
}
}
stepB = a
counterB := 1
for _, child := range children {
if !selectedChild[child] {
assignB(child, centroid, &counterB)
}
}
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
for i := 0; i < m; i++ {
fmt.Fprintln(out, U[i], V[i], weights[i])
}
}