← Home
package main

import (
	"bufio"
	"fmt"
	"os"
)

const INF = int(1 << 60)

type FastScanner struct {
	r *bufio.Reader
}

func NewFastScanner() *FastScanner {
	return &FastScanner{r: bufio.NewReader(os.Stdin)}
}

func (fs *FastScanner) NextInt() int {
	sign := 1
	val := 0
	c, _ := fs.r.ReadByte()
	for (c < '0' || c > '9') && c != '-' {
		c, _ = fs.r.ReadByte()
	}
	if c == '-' {
		sign = -1
		c, _ = fs.r.ReadByte()
	}
	for c >= '0' && c <= '9' {
		val = val*10 + int(c-'0')
		c, _ = fs.r.ReadByte()
	}
	return sign * val
}

func main() {
	in := NewFastScanner()
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	t := in.NextInt()
	for ; t > 0; t-- {
		n := in.NextInt()
		adj := make([][]int, n+1)
		for i := 0; i < n-1; i++ {
			u := in.NextInt()
			v := in.NextInt()
			adj[u] = append(adj[u], v)
			adj[v] = append(adj[v], u)
		}

		parent := make([]int, n+1)
		children := make([][]int, n+1)
		down := make([]int, n+1)
		postOrder := make([]int, 0, n)

		// DFS1: build parent/children and compute down (height)
		type st1 struct {
			u, p, state int
		}
		stack := make([]st1, 0, 2*n)
		stack = append(stack, st1{1, 0, 0})
		parent[1] = 0
		for len(stack) > 0 {
			e := stack[len(stack)-1]
			stack = stack[:len(stack)-1]
			u, p, state := e.u, e.p, e.state
			if state == 0 {
				stack = append(stack, st1{u, p, 1})
				for _, v := range adj[u] {
					if v == p {
						continue
					}
					parent[v] = u
					children[u] = append(children[u], v)
					stack = append(stack, st1{v, u, 0})
				}
			} else {
				mx := 0
				for _, c := range children[u] {
					if down[c] > mx {
						mx = down[c]
					}
				}
				down[u] = mx + 1
				postOrder = append(postOrder, u)
			}
		}

		up := make([]int, n+1)
		A := make([]int, n+1)       // 1 + max neighbor g(neigh,u)
		s2all := make([]int, n+1)   // second smallest among neighbors
		Pval := make([]int, n+1)    // s2_excl(u, parent)
		Bdown := make([]int, n+1)   // min along ancestors of s2_excl(anc, child_on_path)
		for i := 1; i <= n; i++ {
			Bdown[i] = INF
			s2all[i] = INF
			Pval[i] = INF
		}

		// DFS2: compute up[], A[], s2all[], Pval[], Bdown[]
		type st2 struct {
			u, p, curMin int
		}
		stack2 := make([]st2, 0, n)
		up[1] = 0
		stack2 = append(stack2, st2{1, 0, INF})
		for len(stack2) > 0 {
			e := stack2[len(stack2)-1]
			stack2 = stack2[:len(stack2)-1]
			u := e.u
			p := e.p
			curMin := e.curMin

			deg := len(children[u])
			if p != 0 {
				deg++
			}

			// compute maxima and minima among neighbors' g(neigh,u)
			firstMax, secondMax := 0, 0
			m1, m2, m3 := INF, INF, INF
			id1, id2 := -1, -1

			if p != 0 {
				val := up[u]
				if val > firstMax {
					secondMax = firstMax
					firstMax = val
				} else if val > secondMax {
					secondMax = val
				}
				if val < m1 {
					m3 = m2
					m2 = m1
					m1 = val
					id2 = id1
					id1 = p
				} else if val < m2 {
					m3 = m2
					m2 = val
					id2 = p
				} else if val < m3 {
					m3 = val
				}
			}
			for _, c := range children[u] {
				val := down[c]
				if val > firstMax {
					secondMax = firstMax
					firstMax = val
				} else if val > secondMax {
					secondMax = val
				}
				if val < m1 {
					m3 = m2
					m2 = m1
					m1 = val
					id2 = id1
					id1 = c
				} else if val < m2 {
					m3 = m2
					m2 = val
					id2 = c
				} else if val < m3 {
					m3 = val
				}
			}

			A[u] = 1 + firstMax
			if deg >= 2 {
				s2all[u] = m2
			} else {
				s2all[u] = INF
			}

			if p != 0 {
				if deg-1 >= 2 {
					if p == id1 || p == id2 {
						Pval[u] = m3
					} else {
						Pval[u] = m2
					}
				} else {
					Pval[u] = INF
				}
			}

			// For each child: compute valEdge(u->child) for Bdown and up[child]
			for _, c := range children[u] {
				valEdge := INF
				if deg-1 >= 2 {
					if c == id1 || c == id2 {
						valEdge = m3
					} else {
						valEdge = m2
					}
				}
				if curMin < valEdge {
					Bdown[c] = curMin
				} else {
					Bdown[c] = valEdge
				}
				valC := down[c]
				maxExcl := firstMax
				if valC == firstMax {
					maxExcl = secondMax
				}
				up[c] = 1 + maxExcl
				stack2 = append(stack2, st2{c, u, Bdown[c]})
			}
		}

		// minP_subtree using postOrder (children before parent)
		minPSub := make([]int, n+1)
		for i := 1; i <= n; i++ {
			minPSub[i] = Pval[i]
		}
		for _, u := range postOrder {
			mn := minPSub[u]
			for _, c := range children[u] {
				if minPSub[c] < mn {
					mn = minPSub[c]
				}
			}
			minPSub[u] = mn
		}

		// bestOffPath (B_up) via pre-order; bestOff[1] needs special handling
		bestOff := make([]int, n+1)
		for i := 1; i <= n; i++ {
			bestOff[i] = INF
		}
		// pre-order traversal
		st := make([]int, 0, n)
		st = append(st, 1)
		for len(st) > 0 {
			u := st[len(st)-1]
			st = st[:len(st)-1]
			k := len(children[u])
			if k > 0 {
				arr := make([]int, k)
				for i, c := range children[u] {
					arr[i] = minPSub[c]
				}
				pref := make([]int, k)
				suff := make([]int, k)
				for i := 0; i < k; i++ {
					if i == 0 {
						pref[i] = arr[i]
					} else {
						if arr[i] < pref[i-1] {
							pref[i] = arr[i]
						} else {
							pref[i] = pref[i-1]
						}
					}
				}
				for i := k - 1; i >= 0; i-- {
					if i == k-1 {
						suff[i] = arr[i]
					} else {
						if arr[i] < suff[i+1] {
							suff[i] = arr[i]
						} else {
							suff[i] = suff[i+1]
						}
					}
				}
				for i, c := range children[u] {
					siblingMin := INF
					if i > 0 && pref[i-1] < siblingMin {
						siblingMin = pref[i-1]
					}
					if i+1 < k && suff[i+1] < siblingMin {
						siblingMin = suff[i+1]
					}
					v := bestOff[u]
					if siblingMin < v {
						v = siblingMin
					}
					bestOff[c] = v
					st = append(st, c)
				}
			}
		}
		Bup := bestOff
		// Set Bup for root specially: min over all children subtrees
		if len(children[1]) > 0 {
			minv := INF
			for _, c := range children[1] {
				if minPSub[c] < minv {
					minv = minPSub[c]
				}
			}
			Bup[1] = minv
		} else {
			Bup[1] = INF
		}

		// Compute final answers
		bestAns := 0
		for r := 1; r <= n; r++ {
			mm := s2all[r]
			if Bdown[r] < mm {
				mm = Bdown[r]
			}
			if Bup[r] < mm {
				mm = Bup[r]
			}
			ans := A[r]
			if mm < ans {
				ans = mm
			}
			if ans > bestAns {
				bestAns = ans
			}
		}

		fmt.Fprintln(out, bestAns)
	}
}