package main
import (
"bufio"
"io"
"os"
"strconv"
)
const NEG = -1 << 30
type Summary struct {
d1, e1 int
d2, e2 int
diam int
a, b int
}
type FastScanner struct {
data []byte
idx int
}
func (fs *FastScanner) NextInt() int {
n := len(fs.data)
for fs.idx < n {
c := fs.data[fs.idx]
if c >= '0' && c <= '9' {
break
}
fs.idx++
}
val := 0
for fs.idx < n {
c := fs.data[fs.idx]
if c < '0' || c > '9' {
break
}
val = val*10 + int(c-'0')
fs.idx++
}
return val
}
var LOG int
var parent []int
var depthLevel []int
var anc [][]int
var downDepth []int
var downEnd []int
var downDiam []int
var downA []int
var downB []int
var upDepth []int
var upEnd []int
var upDiam []int
var upA []int
var upB []int
var topVals [][3]int
var topIds [][3]int
func emptySummary(u int) Summary {
return Summary{NEG, 0, NEG, 0, 0, u, u}
}
func singleSideSummary(u, depth, end, sideDiam, a, b int) Summary {
s := Summary{depth, end, NEG, 0, sideDiam, a, b}
if depth > s.diam {
s.diam = depth
s.a = u
s.b = end
}
return s
}
func mergeAt(u int, x, y Summary) Summary {
res := Summary{NEG, 0, NEG, 0, x.diam, x.a, x.b}
if y.diam > res.diam {
res.diam = y.diam
res.a = y.a
res.b = y.b
}
add := func(d, e int) {
if d <= NEG/2 {
return
}
if d > res.d1 {
res.d2, res.e2 = res.d1, res.e1
res.d1, res.e1 = d, e
} else if d > res.d2 {
res.d2, res.e2 = d, e
}
}
add(x.d1, x.e1)
add(x.d2, x.e2)
add(y.d1, y.e1)
add(y.d2, y.e2)
if res.d1 > NEG/2 && res.d1 > res.diam {
res.diam = res.d1
res.a = u
res.b = res.e1
}
if res.d2 > NEG/2 && res.d1+res.d2 > res.diam {
res.diam = res.d1 + res.d2
res.a = res.e1
res.b = res.e2
}
return res
}
func insertTop3(vals *[3]int, ids *[3]int, d, id int) {
if d > vals[0] {
vals[2], ids[2] = vals[1], ids[1]
vals[1], ids[1] = vals[0], ids[0]
vals[0], ids[0] = d, id
} else if d > vals[1] {
vals[2], ids[2] = vals[1], ids[1]
vals[1], ids[1] = d, id
} else if d > vals[2] {
vals[2], ids[2] = d, id
}
}
func ascend(u, k int) int {
bit := 0
for k > 0 {
if k&1 == 1 {
u = anc[bit][u]
}
k >>= 1
bit++
}
return u
}
func lca(u, v int) int {
if depthLevel[u] < depthLevel[v] {
u, v = v, u
}
u = ascend(u, depthLevel[u]-depthLevel[v])
if u == v {
return u
}
for j := LOG - 1; j >= 0; j-- {
if anc[j][u] != anc[j][v] {
u = anc[j][u]
v = anc[j][v]
}
}
return parent[u]
}
func dist(u, v int) int {
w := lca(u, v)
return depthLevel[u] + depthLevel[v] - 2*depthLevel[w]
}
func kthOnPath(a, b, l, k int) int {
da := depthLevel[a] - depthLevel[l]
if k <= da {
return ascend(a, k)
}
d := da + depthLevel[b] - depthLevel[l]
return ascend(b, d-k)
}
func getDirectedEndpoints(from, to int) (int, int) {
if parent[from] == to {
return downA[from], downB[from]
}
return upA[to], upB[to]
}
func neutralDepth(c, na, nb int) int {
vals := topVals[c]
ids := topIds[c]
for i := 0; i < 3; i++ {
if ids[i] != na && ids[i] != nb {
if vals[i] < 0 {
return 0
}
return vals[i]
}
}
return 0
}
func main() {
data, _ := io.ReadAll(os.Stdin)
fs := FastScanner{data: data}
n := fs.NextInt()
head := make([]int, n+1)
for i := 1; i <= n; i++ {
head[i] = -1
}
to := make([]int, 2*(n-1))
nxt := make([]int, 2*(n-1))
deg := make([]int, n+1)
edgeIdx := 0
addEdge := func(u, v int) {
to[edgeIdx] = v
nxt[edgeIdx] = head[u]
head[u] = edgeIdx
edgeIdx++
deg[u]++
}
for i := 0; i < n-1; i++ {
u := fs.NextInt()
v := fs.NextInt()
addEdge(u, v)
addEdge(v, u)
}
parent = make([]int, n+1)
depthLevel = make([]int, n+1)
order := make([]int, 0, n)
stack := make([]int, 1)
stack[0] = 1
for len(stack) > 0 {
u := stack[len(stack)-1]
stack = stack[:len(stack)-1]
order = append(order, u)
for e := head[u]; e != -1; e = nxt[e] {
v := to[e]
if v == parent[u] {
continue
}
parent[v] = u
depthLevel[v] = depthLevel[u] + 1
stack = append(stack, v)
}
}
LOG = 1
for (1 << LOG) <= n {
LOG++
}
anc = make([][]int, LOG)
anc[0] = make([]int, n+1)
copy(anc[0], parent)
for j := 1; j < LOG; j++ {
anc[j] = make([]int, n+1)
prev := anc[j-1]
cur := anc[j]
for u := 1; u <= n; u++ {
cur[u] = prev[prev[u]]
}
}
downDepth = make([]int, n+1)
downEnd = make([]int, n+1)
downDiam = make([]int, n+1)
downA = make([]int, n+1)
downB = make([]int, n+1)
for i := n - 1; i >= 0; i-- {
u := order[i]
sum := emptySummary(u)
for e := head[u]; e != -1; e = nxt[e] {
v := to[e]
if v == parent[u] {
continue
}
side := singleSideSummary(u, downDepth[v]+1, downEnd[v], downDiam[v], downA[v], downB[v])
sum = mergeAt(u, sum, side)
}
if sum.d1 > NEG/2 {
downDepth[u] = sum.d1
downEnd[u] = sum.e1
} else {
downDepth[u] = 0
downEnd[u] = u
}
downDiam[u] = sum.diam
downA[u] = sum.a
downB[u] = sum.b
}
upDepth = make([]int, n+1)
upEnd = make([]int, n+1)
upDiam = make([]int, n+1)
upA = make([]int, n+1)
upB = make([]int, n+1)
topVals = make([][3]int, n+1)
topIds = make([][3]int, n+1)
for _, u := range order {
items := make([]Summary, 0, deg[u])
ids := make([]int, 0, deg[u])
for e := head[u]; e != -1; e = nxt[e] {
v := to[e]
if v == parent[u] {
side := singleSideSummary(u, upDepth[u]+1, upEnd[u], upDiam[u], upA[u], upB[u])
items = append(items, side)
ids = append(ids, v)
} else {
side := singleSideSummary(u, downDepth[v]+1, downEnd[v], downDiam[v], downA[v], downB[v])
items = append(items, side)
ids = append(ids, v)
}
}
vals := [3]int{NEG, NEG, NEG}
ids3 := [3]int{}
insertTop3(&vals, &ids3, 0, 0)
for i, it := range items {
insertTop3(&vals, &ids3, it.d1, ids[i])
}
topVals[u] = vals
topIds[u] = ids3
pref := make([]Summary, len(items)+1)
pref[0] = emptySummary(u)
for i := 0; i < len(items); i++ {
pref[i+1] = mergeAt(u, pref[i], items[i])
}
suff := make([]Summary, len(items)+1)
suff[len(items)] = emptySummary(u)
for i := len(items) - 1; i >= 0; i-- {
suff[i] = mergeAt(u, items[i], suff[i+1])
}
for i := 0; i < len(items); i++ {
v := ids[i]
if parent[v] == u {
comb := mergeAt(u, pref[i], suff[i+1])
if comb.d1 > NEG/2 {
upDepth[v] = comb.d1
upEnd[v] = comb.e1
} else {
upDepth[v] = 0
upEnd[v] = u
}
upDiam[v] = comb.diam
upA[v] = comb.a
upB[v] = comb.b
}
}
}
m := fs.NextInt()
out := make([]byte, 0, m*8)
for i := 0; i < m; i++ {
a := fs.NextInt()
b := fs.NextInt()
l := lca(a, b)
d := depthLevel[a] + depthLevel[b] - 2*depthLevel[l]
var ans int
if d&1 == 1 {
k := d / 2
u := kthOnPath(a, b, l, k)
v := kthOnPath(a, b, l, k+1)
p, q := getDirectedEndpoints(u, v)
eccA := dist(a, p)
if t := dist(a, q); t > eccA {
eccA = t
}
p, q = getDirectedEndpoints(v, u)
eccB := dist(b, p)
if t := dist(b, q); t > eccB {
eccB = t
}
if eccA > eccB {
ans = eccA
} else {
ans = eccB
}
} else {
k := d / 2
c := kthOnPath(a, b, l, k)
na := kthOnPath(a, b, l, k-1)
nb := kthOnPath(a, b, l, k+1)
p, q := getDirectedEndpoints(na, c)
eccA := dist(a, p)
if t := dist(a, q); t > eccA {
eccA = t
}
p, q = getDirectedEndpoints(nb, c)
eccB := dist(b, p)
if t := dist(b, q); t > eccB {
eccB = t
}
neutral := k + neutralDepth(c, na, nb)
ans = eccA
if eccB > ans {
ans = eccB
}
if neutral > ans {
ans = neutral
}
}
out = strconv.AppendInt(out, int64(ans), 10)
out = append(out, '\n')
}
w := bufio.NewWriterSize(os.Stdout, 1<<20)
w.Write(out)
w.Flush()
}