← Home
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()
}