package main
import (
"bufio"
"io"
"os"
"strconv"
)
type Pair struct {
cnt int
sum int
}
func better(a, b Pair) bool {
if a.cnt != b.cnt {
return a.cnt > b.cnt
}
return a.sum < b.sum
}
func main() {
data, _ := io.ReadAll(os.Stdin)
idx := 0
nextInt := func() int {
for idx < len(data) && (data[idx] < '0' || data[idx] > '9') {
idx++
}
val := 0
for idx < len(data) && data[idx] >= '0' && data[idx] <= '9' {
val = val*10 + int(data[idx]-'0')
idx++
}
return val
}
n := nextInt()
adj := make([][]int, n+1)
for i := 0; i < n-1; i++ {
u := nextInt()
v := nextInt()
adj[u] = append(adj[u], v)
adj[v] = append(adj[v], u)
}
deg := make([]int, n+1)
for i := 1; i <= n; i++ {
deg[i] = len(adj[i])
}
parent := make([]int, n+1)
order := make([]int, 0, n)
stack := make([]int, 0, n)
stack = append(stack, 1)
parent[1] = -1
for len(stack) > 0 {
v := stack[len(stack)-1]
stack = stack[:len(stack)-1]
order = append(order, v)
for _, to := range adj[v] {
if to == parent[v] {
continue
}
parent[to] = v
stack = append(stack, to)
}
}
dp0 := make([]Pair, n+1)
dp1 := make([]Pair, n+1)
for i := n - 1; i >= 0; i-- {
v := order[i]
p1 := Pair{cnt: 1, sum: deg[v]}
p0 := Pair{}
for _, to := range adj[v] {
if to == parent[v] {
continue
}
p1.cnt += dp0[to].cnt
p1.sum += dp0[to].sum
if better(dp1[to], dp0[to]) {
p0.cnt += dp1[to].cnt
p0.sum += dp1[to].sum
} else {
p0.cnt += dp0[to].cnt
p0.sum += dp0[to].sum
}
}
dp0[v] = p0
dp1[v] = p1
}
rootTake := 0
if better(dp1[1], dp0[1]) {
rootTake = 1
}
selected := make([]bool, n+1)
type State struct {
v int
take int
}
st := make([]State, 0, n)
st = append(st, State{1, rootTake})
for len(st) > 0 {
cur := st[len(st)-1]
st = st[:len(st)-1]
v := cur.v
if cur.take == 1 {
selected[v] = true
for _, to := range adj[v] {
if to == parent[v] {
continue
}
st = append(st, State{to, 0})
}
} else {
for _, to := range adj[v] {
if to == parent[v] {
continue
}
take := 0
if better(dp1[to], dp0[to]) {
take = 1
}
st = append(st, State{to, take})
}
}
}
weights := make([]int, n+1)
for i := 1; i <= n; i++ {
if selected[i] {
weights[i] = deg[i]
} else {
weights[i] = 1
}
}
actualGood := 0
var total int64
for v := 1; v <= n; v++ {
total += int64(weights[v])
var s int64
for _, to := range adj[v] {
s += int64(weights[to])
}
if int64(weights[v]) == s {
actualGood++
}
}
out := bufio.NewWriterSize(os.Stdout, 1<<20)
out.WriteString(strconv.Itoa(actualGood))
out.WriteByte(' ')
out.WriteString(strconv.FormatInt(total, 10))
out.WriteByte('\n')
for i := 1; i <= n; i++ {
if i > 1 {
out.WriteByte(' ')
}
out.WriteString(strconv.Itoa(weights[i]))
}
out.WriteByte('\n')
out.Flush()
}