Fishing Prince loves trees, and he especially loves trees with only one centroid. The tree is a connected graph without cycles.

A vertex is a centroid of a tree only when you cut this vertex (remove it and remove all edges from this vertex), the size of the largest connected component of the remaining graph is the smallest possible.

For example, the centroid of the following tree is $2$, because when you cut it, the size of the largest connected component of the remaining graph is $2$ and it can't be smaller. [Image] 

However, in some trees, there might be more than one centroid, for example: [Image] 

Both vertex $1$ and vertex $2$ are centroids because the size of the largest connected component is $3$ after cutting each of them.

Now Fishing Prince has a tree. He should cut one edge of the tree (it means to remove the edge). After that, he should add one edge. The resulting graph after these two operations should be a tree. He can add the edge that he cut.

He wants the centroid of the resulting tree to be unique. Help him and find any possible way to make the operations. It can be proved, that at least one such way always exists.


-----Input-----

The input consists of multiple test cases. The first line contains an integer $t$ ($1\leq t\leq 10^4$) — the number of test cases. The description of the test cases follows.

The first line of each test case contains an integer $n$ ($3\leq n\leq 10^5$) — the number of vertices.

Each of the next $n-1$ lines contains two integers $x, y$ ($1\leq x,y\leq n$). It means, that there exists an edge connecting vertices $x$ and $y$.

It's guaranteed that the given graph is a tree.

It's guaranteed that the sum of $n$ for all test cases does not exceed $10^5$.


-----Output-----

For each test case, print two lines.

In the first line print two integers $x_1, y_1$ ($1 \leq x_1, y_1 \leq n$), which means you cut the edge between vertices $x_1$ and $y_1$. There should exist edge connecting vertices $x_1$ and $y_1$.

In the second line print two integers $x_2, y_2$ ($1 \leq x_2, y_2 \leq n$), which means you add the edge between vertices $x_2$ and $y_2$.

The graph after these two operations should be a tree.

If there are multiple solutions you can print any.


-----Example-----
Input
2
5
1 2
1 3
2 4
2 5
6
1 2
1 3
1 4
2 5
2 6

Output
1 2
1 2
1 3
2 3


-----Note-----

Note that you can add the same edge that you cut.

In the first test case, after cutting and adding the same edge, the vertex $2$ is still the only centroid.

In the second test case, the vertex $2$ becomes the only centroid after cutting the edge between vertices $1$ and $3$ and adding the edge between vertices $2$ and $3$.

Difficulty: MEDIUM_HARD
Tags: Tree algorithms

Graph algorithms

Graph traversal

Constructive algorithms

Starter code:

Solutions:
import os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
cases = int(input())
for t in range(cases):
	n = int(input())
	newd = {i + 1: [] for i in range(n)}
	for i in range(n - 1):
		(x, y) = list(map(int, input().split()))
		newd[x].append(y)
		newd[y].append(x)
	visited = {i: True for i in newd}
	children = {i: 0 for i in newd}
	parent = {i: 0 for i in newd}
	start = 1
	for i in newd:
		if len(newd[i]) == 1:
			start = i
			break
	stack = [start]
	while stack:
		node = stack.pop()
		if visited[node]:
			visited[node] = False
			stack.append(node)
			c = 0
			for i in newd[node]:
				if visited[i]:
					stack.append(i)
					parent[i] = node
		elif parent[node]:
			children[parent[node]] += children[node] + 1
	if n % 2 == 1:
		print(start, newd[start][0])
		print(newd[start][0], start)
	else:
		f = 0
		for i in newd:
			if 2 * (children[i] + 1) == n:
				print(start, newd[start][0])
				print(start, i)
				f = 1
				break
		if f == 0:
			print(start, newd[start][0])
			print(newd[start][0], start)


import os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
t = int(input())
for _ in range(t):
	n = int(input())
	graph = []
	for i in range(n + 1):
		graph.append([])
	edges = []
	for i in range(n - 1):
		(x, y) = map(int, input().split())
		graph[x].append(y)
		graph[y].append(x)
		edges.append([x, y])
	for i in range(1, n + 1):
		if len(graph[i]) == 1:
			start = i
			break
	stack = []
	stack.append(start)
	visited = [False] * (n + 1)
	children = [0] * (n + 1)
	parent = [-1] * (n + 1)
	while len(stack) != 0:
		s = stack.pop()
		if not visited[s]:
			visited[s] = True
			stack.append(s)
			for i in range(len(graph[s])):
				if not visited[graph[s][i]]:
					stack.append(graph[s][i])
					parent[graph[s][i]] = s
		elif parent[s] != -1:
			children[parent[s]] += children[s] + 1
	flag = 0
	for i in range(1, n + 1):
		if 2 * (children[i] + 1) == n:
			print(start, graph[start][0])
			print(start, i)
			flag = 1
			break
	if flag == 0:
		print(start, graph[start][0])
		print(start, graph[start][0])


def findCentroids(v, parent):
	flag = True
	q = [[~v, parent], [v]]
	visited = [0] * N
	while q:
		V = q.pop()
		if V[0] >= 0:
			visited[V[0]] = 1
			for u in adj[V[0]]:
				if visited[u]:
					continue
				q.append([~u, V[0]])
				q.append([u])
		else:
			flag = True
			memo[~V[0]] = 1
			for u in adj[~V[0]]:
				if u == V[1]:
					continue
				if memo[u] > N / 2:
					flag = False
				memo[~V[0]] += memo[u]
			if N - memo[~V[0]] > N / 2:
				flag = False
			if flag:
				centroids.append(~V[0])
t = int(input())
for _ in range(t):
	N = int(input())
	adj = [[] for _ in range(N)]
	for _ in range(N - 1):
		(x, y) = map(lambda x: int(x) - 1, input().split())
		adj[x].append(y)
		adj[y].append(x)
	memo = [None] * N
	centroids = []
	findCentroids(0, N)
	centroids.sort()
	if len(centroids) == 1:
		print(1, adj[0][0] + 1)
		print(1, adj[0][0] + 1)
	else:
		for j in range(N):
			if j in adj[centroids[0]] and j != centroids[0] and (j != centroids[1]):
				print(1 + centroids[0], 1 + j)
				print(1 + centroids[1], 1 + j)
				break


from collections import defaultdict
import sys
import threading
ans = 100000.0

def dfs1(i, p):
	c = 1
	for j in tree[i]:
		if j != p:
			c += dfs1(j, i)
	dic[p, i] = c
	dic[i, p] = n - c
	return c

def dfs2(i, p):
	global ans
	tmp = dic[i, p]
	for j in tree[i]:
		if j != p:
			dfs2(j, i)
			tmp = max(tmp, dic[i, j])
	ans = min(ans, tmp)

def dfs3(i, p):
	tmp = dic[i, p]
	for j in tree[i]:
		if j != p:
			dfs3(j, i)
			tmp = max(tmp, dic[i, j])
	if ans == tmp:
		res.append(i)

def solve():
	global ans, tree, dic, n, res
	t = int(input())
	for _ in range(t):
		n = int(input())
		ans = 100000.0
		res = []
		tree = [[] for _ in range(n + 1)]
		dic = defaultdict()
		for _ in range(n - 1):
			(x, y) = map(int, input().split())
			tree[x].append(y)
			tree[y].append(x)
		dfs1(1, 0)
		dfs2(1, 0)
		dfs3(1, 0)
		if len(res) == 1:
			a = res[0]
			b = tree[a][0]
			print(a, b)
			print(a, b)
		else:
			(a, b) = (res[0], res[1])
			c = 0
			for j in tree[a]:
				if j != b:
					c = j
					break
			print(a, c)
			print(b, c)
res = []
tree = []
dic = []
n = 0
max_recur_size = 10 ** 5 * 2 + 1000
max_stack_size = max_recur_size * 500
sys.setrecursionlimit(max_recur_size)
threading.stack_size(max_stack_size)
thread = threading.Thread(target=solve)
thread.start()


def getInts():
	return [int(s) for s in input().split()]

def getInt():
	return int(input())

def getStrs():
	return [s for s in input().split()]

def getStr():
	return input()

def listStr():
	return list(input())
import collections as col
import sys
sys.setrecursionlimit(10 ** 5 + 5)
from types import GeneratorType

def solve():

	def bootstrap(f, stack=[]):

		def wrappedfunc(*args, **kwargs):
			if stack:
				return f(*args, **kwargs)
			else:
				to = f(*args, **kwargs)
				while True:
					if type(to) is GeneratorType:
						stack.append(to)
						to = next(to)
					else:
						stack.pop()
						if not stack:
							break
						to = stack[-1].send(to)
				return to
		return wrappedfunc

	@bootstrap
	def numberOfNodes(s, e):
		count1[s] = 1
		for u in graph[s]:
			if u == e:
				continue
			yield numberOfNodes(u, s)
			count1[s] += count1[u]
		yield
	N = getInt()
	count1 = [0] * (N + 1)
	graph = col.defaultdict(set)
	for n in range(N - 1):
		(x, y) = getInts()
		graph[y].add(x)
		graph[x].add(y)
	max_subtree = 0
	max_neighbour = 0
	root = 1
	numberOfNodes(1, 0)
	for neighbour in graph[root]:
		c = count1[neighbour]
		if c > max_subtree:
			max_subtree = count1[neighbour]
			max_neighbour = neighbour
	while max_subtree > N / 2:
		prev_root = root
		root = max_neighbour
		max_subtree = N - max_subtree
		max_neighbour = prev_root
		for neighbour in graph[root]:
			if neighbour != prev_root:
				c = count1[neighbour]
				if c > max_subtree:
					max_subtree = count1[neighbour]
					max_neighbour = neighbour
	if max_subtree < N / 2:
		for x in graph[root]:
			print(root, x)
			print(root, x)
			return
	for nn in graph[max_neighbour]:
		if nn != root:
			print(max_neighbour, nn)
			print(root, nn)
			return
T = getInt()
for t in range(T):
	solve()


import sys, os, io

def rs():
	return sys.stdin.readline().rstrip()

def ri():
	return int(sys.stdin.readline())

def ria():
	return list(map(int, sys.stdin.readline().split()))

def ws(s):
	sys.stdout.write(s + '\n')

def wi(n):
	sys.stdout.write(str(n) + '\n')

def wia(a):
	sys.stdout.write(' '.join([str(x) for x in a]) + '\n')
import math, datetime, functools, itertools, operator, bisect, fractions, statistics
from collections import deque, defaultdict, OrderedDict, Counter
from fractions import Fraction
from decimal import Decimal
from sys import stdout
from heapq import heappush, heappop, heapify, _heapify_max, _heappop_max, nsmallest, nlargest
INF = 999999999999999999999999
alphabets = 'abcdefghijklmnopqrstuvwxyz'

class SortedList:

	def __init__(self, iterable=[], _load=200):
		values = sorted(iterable)
		self._len = _len = len(values)
		self._load = _load
		self._lists = _lists = [values[i:i + _load] for i in range(0, _len, _load)]
		self._list_lens = [len(_list) for _list in _lists]
		self._mins = [_list[0] for _list in _lists]
		self._fen_tree = []
		self._rebuild = True

	def _fen_build(self):
		self._fen_tree[:] = self._list_lens
		_fen_tree = self._fen_tree
		for i in range(len(_fen_tree)):
			if i | i + 1 < len(_fen_tree):
				_fen_tree[i | i + 1] += _fen_tree[i]
		self._rebuild = False

	def _fen_update(self, index, value):
		if not self._rebuild:
			_fen_tree = self._fen_tree
			while index < len(_fen_tree):
				_fen_tree[index] += value
				index |= index + 1

	def _fen_query(self, end):
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		x = 0
		while end:
			x += _fen_tree[end - 1]
			end &= end - 1
		return x

	def _fen_findkth(self, k):
		_list_lens = self._list_lens
		if k < _list_lens[0]:
			return (0, k)
		if k >= self._len - _list_lens[-1]:
			return (len(_list_lens) - 1, k + _list_lens[-1] - self._len)
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		idx = -1
		for d in reversed(range(len(_fen_tree).bit_length())):
			right_idx = idx + (1 << d)
			if right_idx < len(_fen_tree) and k >= _fen_tree[right_idx]:
				idx = right_idx
				k -= _fen_tree[idx]
		return (idx + 1, k)

	def _delete(self, pos, idx):
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len -= 1
		self._fen_update(pos, -1)
		del _lists[pos][idx]
		_list_lens[pos] -= 1
		if _list_lens[pos]:
			_mins[pos] = _lists[pos][0]
		else:
			del _lists[pos]
			del _list_lens[pos]
			del _mins[pos]
			self._rebuild = True

	def _loc_left(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(lo, pos) = (-1, len(_lists) - 1)
		while lo + 1 < pos:
			mi = lo + pos >> 1
			if value <= _mins[mi]:
				pos = mi
			else:
				lo = mi
		if pos and value <= _lists[pos - 1][-1]:
			pos -= 1
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value <= _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def _loc_right(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(pos, hi) = (0, len(_lists))
		while pos + 1 < hi:
			mi = pos + hi >> 1
			if value < _mins[mi]:
				hi = mi
			else:
				pos = mi
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value < _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def add(self, value):
		_load = self._load
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len += 1
		if _lists:
			(pos, idx) = self._loc_right(value)
			self._fen_update(pos, 1)
			_list = _lists[pos]
			_list.insert(idx, value)
			_list_lens[pos] += 1
			_mins[pos] = _list[0]
			if _load + _load < len(_list):
				_lists.insert(pos + 1, _list[_load:])
				_list_lens.insert(pos + 1, len(_list) - _load)
				_mins.insert(pos + 1, _list[_load])
				_list_lens[pos] = _load
				del _list[_load:]
				self._rebuild = True
		else:
			_lists.append([value])
			_mins.append(value)
			_list_lens.append(1)
			self._rebuild = True

	def discard(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_right(value)
			if idx and _lists[pos][idx - 1] == value:
				self._delete(pos, idx - 1)

	def remove(self, value):
		_len = self._len
		self.discard(value)
		if _len == self._len:
			raise ValueError('{0!r} not in list'.format(value))

	def pop(self, index=-1):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		value = self._lists[pos][idx]
		self._delete(pos, idx)
		return value

	def bisect_left(self, value):
		(pos, idx) = self._loc_left(value)
		return self._fen_query(pos) + idx

	def bisect_right(self, value):
		(pos, idx) = self._loc_right(value)
		return self._fen_query(pos) + idx

	def count(self, value):
		return self.bisect_right(value) - self.bisect_left(value)

	def __len__(self):
		return self._len

	def __getitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		return self._lists[pos][idx]

	def __delitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		self._delete(pos, idx)

	def __contains__(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_left(value)
			return idx < len(_lists[pos]) and _lists[pos][idx] == value
		return False

	def __iter__(self):
		return (value for _list in self._lists for value in _list)

	def __reversed__(self):
		return (value for _list in reversed(self._lists) for value in reversed(_list))

	def __repr__(self):
		return 'SortedList({0})'.format(list(self))

class SegTree:

	def __init__(self, n):
		self.N = 1 << n.bit_length()
		self.tree = [0] * (self.N << 1)

	def update(self, i, j, v):
		i += self.N
		j += self.N
		while i <= j:
			if i % 2 == 1:
				self.tree[i] += v
			if j % 2 == 0:
				self.tree[j] += v
			(i, j) = (i + 1 >> 1, j - 1 >> 1)

	def query(self, i):
		v = 0
		i += self.N
		while i > 0:
			v += self.tree[i]
			i >>= 1
		return v

def SieveOfEratosthenes(limit):
	isPrime = [True] * (limit + 1)
	isPrime[0] = isPrime[1] = False
	primes = []
	for i in range(2, limit + 1):
		if not isPrime[i]:
			continue
		primes += [i]
		for j in range(i * i, limit + 1, i):
			isPrime[j] = False
	return primes

def main():
	mod = 1000000007
	starttime = datetime.datetime.now()
	if os.path.exists('input.txt'):
		sys.stdin = open('input.txt', 'r')
		sys.stdout = open('output.txt', 'w')
	tc = 1
	tc = ri()
	for _ in range(tc):
		n = ri()
		graph = [[] for i in range(n + 1)]
		for i in range(n - 1):
			(a, b) = ria()
			graph[a].append(b)
			graph[b].append(a)
		centroidposs = [1] * (n + 1)

		def dfs(graph):
			start = 1
			dp = [0] * (n + 1)
			(visited, finished) = ([False] * (n + 1), [False] * (n + 1))
			stack = [start]
			while stack:
				start = stack[-1]
				if not visited[start]:
					visited[start] = True
					for child in graph[start]:
						if not visited[child]:
							stack.append(child)
				else:
					stack.pop()
					dp[start] += 1
					for child in graph[start]:
						if finished[child]:
							dp[start] += dp[child]
							if dp[child] > n // 2:
								centroidposs[start] = 0
					if n - dp[start] > n // 2:
						centroidposs[start] = 0
					finished[start] = True
		dfs(graph)
		centroids = []
		for i in range(1, n + 1):
			if centroidposs[i]:
				centroids.append(i)
		if len(centroids) == 1:
			print(1, graph[1][0])
			print(1, graph[1][0])
		else:
			(a, b) = centroids
			for i in graph[a]:
				if i != b:
					break
			print(a, i)
			print(b, i)
	endtime = datetime.datetime.now()
	time = (endtime - starttime).total_seconds() * 1000
	if os.path.exists('input.txt'):
		print('Time:', time, 'ms')

class FastReader(io.IOBase):
	newlines = 0

	def __init__(self, fd, chunk_size=1024 * 8):
		self._fd = fd
		self._chunk_size = chunk_size
		self.buffer = io.BytesIO()

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, self._chunk_size))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self, size=-1):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, self._chunk_size if size == -1 else size))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

class FastWriter(io.IOBase):

	def __init__(self, fd):
		self._fd = fd
		self.buffer = io.BytesIO()
		self.write = self.buffer.write

	def flush(self):
		os.write(self._fd, self.buffer.getvalue())
		(self.buffer.truncate(0), self.buffer.seek(0))

class FastStdin(io.IOBase):

	def __init__(self, fd=0):
		self.buffer = FastReader(fd)
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

class FastStdout(io.IOBase):

	def __init__(self, fd=1):
		self.buffer = FastWriter(fd)
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.flush = self.buffer.flush
sys.stdin = FastStdin()
sys.stdout = FastStdout()
main()


import os, sys
from io import BytesIO, IOBase
from collections import defaultdict
from copy import deepcopy

def dfs(path):
	rishta = defaultdict(dict)
	su = defaultdict(int)
	st = [1]
	while len(st):
		if not len(path[st[-1]]):
			y = st.pop()
			su[y] += 1
			if len(st):
				su[st[-1]] += su[y]
				rishta[st[-1]][y] = su[y]
			continue
		x = path[st[-1]].pop()
		path[x].remove(st[-1])
		st.append(x)
	return rishta

def main():
	for _ in range(int(input())):
		n = int(input())
		path = defaultdict(set)
		for _ in range(n - 1):
			(a, b) = map(int, input().split())
			path[a].add(b)
			path[b].add(a)
		if n % 2:
			x = path[1].pop()
			print(1, x)
			print(1, x)
			continue
		path1 = deepcopy(path)
		rishta = dfs(path)
		tar = n // 2
		req = (-1, -1)
		for i in rishta:
			for j in rishta[i]:
				if rishta[i][j] == tar:
					req = (i, j)
					break
		if req == (-1, -1):
			x = path1[1].pop()
			print(1, x)
			print(1, x)
			continue
		path1[req[1]].remove(req[0])
		st = [req[1]]
		while len(st):
			if not len(path1[st[-1]]):
				break
			i = path1[st[-1]].pop()
			path1[i].remove(st[-1])
			st.append(i)
		(a, b) = (st[-2], st[-1])
		print(a, b)
		print(req[0], b)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


import threading
import sys
threading.stack_size(16 * 2048 * 2048)
sys.setrecursionlimit(100010)
import io, os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

def gettot(index, father, neigh, maxindex, maxsubtree):
	n = len(neigh)
	upper = n - 1
	maximum = 0
	for ele in neigh[index]:
		if ele == father:
			continue
		sub = gettot(ele, index, neigh, maxindex, maxsubtree)
		upper -= sub
		if sub > maximum:
			maximum = sub
			maxindex[index] = ele
			maxsubtree[index] = sub
	if upper > maximum:
		maxindex[index] = father
		maxsubtree[index] = upper
	return n - upper

def main():
	T = int(input())
	r = 1
	while r <= T:
		n = int(input())
		neigh = [[] for i in range(n)]
		first = []
		for i in range(n - 1):
			(u, v) = map(int, input().split())
			if not first:
				first.append([u, v])
			neigh[u - 1].append(v - 1)
			neigh[v - 1].append(u - 1)
		maxsubtree = [0] * n
		maxindex = [-1] * n
		visited = [False] * n
		gettot(0, -1, neigh, maxindex, maxsubtree)
		minimum = min(maxsubtree)
		min_index = []
		for i in range(n):
			if maxsubtree[i] == minimum:
				min_index.append(i)
		if len(min_index) == 1:
			print(first[0][0], first[0][1])
			print(first[0][0], first[0][1])
		else:
			a = maxindex[min_index[0]]
			for ele in neigh[a]:
				if ele == min_index[0]:
					continue
				print(a + 1, ele + 1)
				print(min_index[0] + 1, ele + 1)
				break
		r += 1
threading.Thread(target=main).start()


import io
import os
from collections import Counter, defaultdict, deque

def solve(n, edges):
	graph = [[] for i in range(n)]
	for (u, v) in edges:
		graph[u].append(v)
		graph[v].append(u)
	isLeaf = [False] * n
	for u in range(n):
		if len(graph[u]) == 1:
			isLeaf[u] = True
	parent = {}
	bfs = [n - 1]
	for node in bfs:
		bfs += graph[node]
		for nei in graph[node]:
			parent[nei] = node
			graph[nei].remove(node)
	size = [0] * n
	for node in reversed(bfs):
		size[node] = 1 + sum((size[child] for child in graph[node]))

	def getAdjSize(u):
		sizes = [size[v] for v in graph[u]]
		if u in parent:
			lastSize = n - 1 - sum(sizes)
			sizes.append(lastSize)
		return sizes
	cands = []
	compSize = float('inf')
	for u in range(n):
		sizes = getAdjSize(u)
		mx = max(sizes)
		if mx < compSize:
			cands = [u]
			compSize = mx
		elif mx == compSize:
			cands.append(u)
	if len(cands) == 1:
		line = str(edges[0][0] + 1) + ' ' + str(edges[0][1] + 1)
		return line + '\n' + line
	assert n % 2 == 0
	assert len(cands) == 2
	assert cands in edges or cands[::-1] in edges

	def getAdjSizeDict(u):
		sizes = {v: size[v] for v in graph[u]}
		if u in parent:
			sizes[parent[u]] = n - 1 - sum(sizes.values())
		return sizes

	def findLeaf(source, exclude):
		assert not isLeaf[source]
		q = deque([source])
		seen = set()
		while q:
			node = q.popleft()
			extras = []
			if node in parent:
				extras.append(parent[node])
			for nbr in graph[node] + extras:
				if nbr != exclude and nbr not in seen:
					q.append(nbr)
					seen.add(nbr)
					if isLeaf[nbr]:
						return (node, nbr)
	(c1, c2) = cands
	size1 = getAdjSizeDict(c1)
	size2 = getAdjSizeDict(c2)
	assert size1[c2] == size2[c1] == compSize
	del size1[c2]
	del size2[c1]
	for (k, l) in size1.items():
		if l >= 2:
			(u, v) = findLeaf(k, c1)
			return str(u + 1) + ' ' + str(v + 1) + '\n' + str(c2 + 1) + ' ' + str(v + 1)
	for (k, l) in size2.items():
		if l >= 2:
			(u, v) = findLeaf(k, c2)
			return str(u + 1) + ' ' + str(v + 1) + '\n' + str(c1 + 1) + ' ' + str(v + 1)
	v = next(iter(size1.keys()))
	assert isLeaf[v]
	return str(c1 + 1) + ' ' + str(v + 1) + '\n' + str(c2 + 1) + ' ' + str(v + 1)
if False:
	import networkx as nx
	for _ in range(100):
		for n in [3, 10]:
			print('tc', _, n)
			graph = nx.random_tree(n, seed=_)
			edges = []
			for (u, v) in graph.edges:
				edges.append([u, v])
			print(n, edges)
			print(solve(n, edges))
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
TC = int(input())
for tc in range(1, TC + 1):
	(N,) = [int(x) for x in input().split()]
	edges = [[int(x) - 1 for x in input().split()] for i in range(N - 1)]
	ans = solve(N, edges)
	print(ans)


from collections import deque
import sys

def input():
	return sys.stdin.readline()[:-1]

def main():
	T = int(input())
	for i in range(T):
		N = int(input())
		e_list = [[] for i in range(N)]
		for i in range(N - 1):
			(a, b) = list(map(int, input().split()))
			(a, b) = (a - 1, b - 1)
			e_list[a].append(b)
			e_list[b].append(a)
		vi = 0
		INF = 10 ** 27
		Q = deque([vi])
		checked_list = [False] * N
		checked_list[vi] = True
		min_path_list = [INF] * N
		min_path_list[vi] = 0
		while len(Q) > 0:
			v = Q.pop()
			for v1 in e_list[v]:
				if not checked_list[v1]:
					checked_list[v1] = True
					Q.appendleft(v1)
					min_path_list[v1] = min(min_path_list[v1], min_path_list[v] + 1)
		min_p = [(i, d) for (i, d) in enumerate(min_path_list)]
		min_p.sort(key=lambda x: x[1], reverse=True)
		member = [0] * N
		center = []
		for z in min_p:
			flag = True
			(i, d) = z
			mem = 0
			for v in e_list[i]:
				mem += member[v]
				if member[v] > N / 2:
					flag = False
			member[i] = mem + 1
			if flag and N - member[i] <= N / 2:
				center.append(i)
		if len(center) == 1:
			print(1, e_list[0][0] + 1)
			print(1, e_list[0][0] + 1)
		elif e_list[center[0]][0] != center[1]:
			print(center[0] + 1, e_list[center[0]][0] + 1)
			print(center[1] + 1, e_list[center[0]][0] + 1)
		else:
			print(center[0] + 1, e_list[center[0]][1] + 1)
			print(center[1] + 1, e_list[center[0]][1] + 1)

def __starting_point():
	main()
__starting_point()


import math
t = int(input())
while t > 0:
	n = int(input())
	tree = [[] for i in range(0, n + 1)]
	for i in range(0, n - 1):
		(x, y) = map(int, input().split())
		tree[x].append(y)
		tree[y].append(x)
	size = [1] * (n + 1)
	stack = [(1, False)]
	result = None
	in_stack = [False] * (n + 1)
	in_stack[1] = True
	while stack and n % 2 == 0:
		(parent, visited) = stack.pop()
		if visited:
			in_stack[parent] = False
			for child in tree[parent]:
				if size[child] == int(n / 2):
					removal_node = next((node for node in tree[child] if node != parent))
					result = [(child, removal_node), (parent, removal_node)]
					break
				if not in_stack[child]:
					size[parent] += size[child]
		else:
			stack.append((parent, True))
			for child in tree[parent]:
				if not in_stack[child]:
					stack.append((child, False))
					in_stack[child] = True
	if result:
		print('{} {}'.format(result[0][0], result[0][1]))
		print('{} {}'.format(result[1][0], result[1][1]))
	else:
		print('{} {}'.format(1, tree[1][0]))
		print('{} {}'.format(1, tree[1][0]))
	t -= 1


import sys
input = sys.stdin.readline
t = int(input())
for i in range(t):
	n = int(input())
	A = [[] for _ in range(n)]
	depth = [None for _ in range(n)]
	subtree_size = [0 for _ in range(n)]
	lcc = [None for _ in range(n)]
	for i in range(n - 1):
		(x, y) = map(int, input().split(' '))
		x -= 1
		y -= 1
		A[x].append(y)
		A[y].append(x)
	queue = [0]
	d = 0
	visit_order = []
	while queue:
		next_queue = []
		for root in queue:
			visit_order.append(root)
			depth[root] = d
			for v in A[root]:
				if depth[v] is None:
					next_queue.append(v)
		d += 1
		queue = next_queue
	for root in reversed(visit_order):
		size = 0
		biggest_child = 0
		for v in A[root]:
			if depth[v] > depth[root]:
				child_size = subtree_size[v]
				biggest_child = max(biggest_child, child_size)
				size += child_size
		subtree_size[root] = size + 1
		lcc[root] = max(biggest_child, n - size - 1)
	centroid_lcc = min(lcc)
	centroids = [i for i in range(n) if lcc[i] == centroid_lcc]
	if len(centroids) == 1:
		print(x + 1, y + 1)
		print(x + 1, y + 1)
	else:
		(centroid_1, centroid_2) = centroids
		if len(A[centroid_1]) > 1:
			other = [x for x in A[centroid_1] if x != centroid_2][0]
			print(centroid_1 + 1, other + 1)
			print(centroid_2 + 1, other + 1)


import os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
for _ in range(int(input())):
	n = int(input())
	adjacencyList = []
	for _ in range(n):
		adjacencyList.append([])
	anyEdge = (0, 0)
	for _ in range(n - 1):
		(x, y) = map(int, input().split())
		adjacencyList[x - 1].append(y - 1)
		adjacencyList[y - 1].append(x - 1)
		anyEdge = (x, y)
	parentNode = [-1] * n
	numberDaughter = [0] * n
	isTraversed = [False] * n
	isTraversed[0] = True
	dfsStack = [0]
	readyVertexStack = []
	while dfsStack:
		curVertex = dfsStack.pop()
		for elem in adjacencyList[curVertex]:
			if not isTraversed[elem]:
				isTraversed[elem] = True
				parentNode[elem] = curVertex
				dfsStack.append(elem)
				numberDaughter[curVertex] += 1
		if numberDaughter[curVertex] == 0:
			readyVertexStack.append(curVertex)
	subtreeSize = [0] * n
	minConnectedComponentSize = n
	centroid = []
	while readyVertexStack:
		curVertex = readyVertexStack.pop()
		maxSubtree = 0
		for elem in adjacencyList[curVertex]:
			if elem == parentNode[curVertex]:
				numberDaughter[elem] -= 1
				if numberDaughter[elem] == 0:
					readyVertexStack.append(elem)
			else:
				if subtreeSize[elem] > maxSubtree:
					maxSubtree = subtreeSize[elem]
				subtreeSize[curVertex] += subtreeSize[elem]
		subtreeSize[curVertex] += 1
		if maxSubtree < n - subtreeSize[curVertex]:
			maxSubtree = n - subtreeSize[curVertex]
		if minConnectedComponentSize > maxSubtree:
			minConnectedComponentSize = maxSubtree
			centroid = [curVertex]
		elif minConnectedComponentSize == maxSubtree:
			centroid.append(curVertex)
	if len(centroid) == 1:
		print(' '.join(map(str, anyEdge)))
		print(' '.join(map(str, anyEdge)))
	else:
		edge1 = [centroid[0] + 1]
		edge2 = [centroid[1] + 1]
		for elem in adjacencyList[centroid[0]]:
			if elem != centroid[1]:
				edge1.append(elem + 1)
				edge2.append(elem + 1)
				break
		print(' '.join(map(str, edge1)))
		print(' '.join(map(str, edge2)))


import sys, threading
inp = sys.stdin.buffer.readline
inar = lambda : list(map(int, inp().split()))
inin = lambda : int(inp())
inst = lambda : inp().decode().rstrip('\n\r')

def centroid(g):
	n = len(g)
	centroid = []
	size = [0 for i in range(n)]

	def dfs(node, par):
		size[node] = 1
		iscent = True
		for nei in g[node]:
			if nei != par:
				dfs(nei, node)
				size[node] += size[nei]
				if size[nei] > n // 2:
					iscent = False
		if n - size[node] > n // 2:
			iscent = False
		if iscent:
			centroid.append(node)
	dfs(0, -1)
	return (centroid, size)

def main():
	_T_ = inin()
	for _t_ in range(_T_):
		n = inin()
		gr = [[] for i in range(n)]
		vis = [False for i in range(n)]
		for i in range(n - 1):
			(x, y) = inar()
			x -= 1
			y -= 1
			gr[x].append(y)
			gr[y].append(x)
		(cent, size) = centroid(gr)
		if len(cent) == 1:
			print(x + 1, y + 1)
			print(x + 1, y + 1)
		else:
			opponent = -1
			maxsize = -12
			to_remove = -1
			for node in cent:
				for nei in gr[node]:
					if size[nei] > maxsize and nei not in cent:
						maxsize = size[nei]
						opponent = node
						to_remove = nei
			if opponent == cent[0]:
				print(cent[0] + 1, to_remove + 1)
				print(cent[1] + 1, to_remove + 1)
			else:
				print(cent[1] + 1, to_remove + 1)
				print(cent[0] + 1, to_remove + 1)
sys.setrecursionlimit(10 ** 6)
threading.stack_size(10 ** 8)
t = threading.Thread(target=main)
t.start()
t.join()


import sys
import threading

def dfs(d, i, arr, k):
	arr[i - 1] = 1
	for j in d[i]:
		if k != j:
			x = dfs(d, j, arr, i)
			arr[i - 1] += x
	return arr[i - 1]

def main():
	for _ in range(int(input())):
		n = int(input())
		d = [[] for i in range(n + 1)]
		for i in range(1, n):
			(u, v) = map(int, input().split())
			d[u].append(v)
			d[v].append(u)
		arr = [1] * n
		dfs(d, 1, arr, -1)
		w = [1] * n
		for i in range(n):
			m = n - arr[i]
			for j in d[i + 1]:
				if arr[j - 1] <= arr[i]:
					m = max(m, arr[j - 1])
			w[i] = m
		if w.count(min(w)) == 1:
			print(u, v)
			print(u, v)
		else:
			x = min(w)
			l = []
			for i in range(n):
				if w[i] == x:
					l.append(i)
			(l[1], l[0]) = (l[0], l[1])
			if d[l[0] + 1][0] != l[1] + 1:
				print(l[0] + 1, d[l[0] + 1][0])
				print(l[1] + 1, d[l[0] + 1][0])
			else:
				print(l[0] + 1, d[l[0] + 1][1])
				print(l[1] + 1, d[l[0] + 1][1])
max_recur_size = 10 ** 5 * 2 + 1000
max_stack_size = max_recur_size * 500
sys.setrecursionlimit(max_recur_size)
threading.stack_size(max_stack_size)
thread = threading.Thread(target=main)
thread.start()


import sys

def input():
	return sys.stdin.readline().strip()
for _ in range(int(input())):
	N = int(input())
	if N % 2:
		s = input()
		print(s)
		print(s)
		for i in range(N - 2):
			input()
		continue
	V = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		V[x - 1] += [y - 1]
		V[y - 1] += [x - 1]
	que = [0]
	X = [1] * N
	P = [-1] * N
	C = [0] * N
	while que:
		q = que.pop()
		if V[q]:
			q1 = V[q].pop()
			if q1 == P[q]:
				que += [q]
				continue
			P[q1] = q
			que += [q1]
			C[q] = q1
		elif q:
			X[P[q]] += X[q]
			que += [P[q]]
	if N // 2 in X:
		i = X.index(N // 2)
		j = i
		while C[j]:
			j = C[j]
		print(j + 1, P[j] + 1)
		print(P[i] + 1, j + 1)
	else:
		print(1, C[0] + 1)
		print(1, C[0] + 1)


import sys, threading
from sys import stdin, stdout
sys.setrecursionlimit(10 ** 9)
threading.stack_size(16 * 2048 * 2048)
graph = []
centroids = []
size = []
n = 0

def dfs(vertex, parent):
	size[vertex] = 1
	is_centroid = True
	edge = (parent, vertex)
	for adj in graph[vertex]:
		if adj != parent:
			last_edge = dfs(adj, vertex)
			size[vertex] += size[adj]
			edge = last_edge
			if size[adj] > n / 2:
				is_centroid = False
	if n - size[vertex] > n / 2:
		is_centroid = False
	if is_centroid:
		centroids.append([vertex, *last_edge])
	return edge

def compute_centroids():
	global size
	size = [0] * len(graph)
	global centroids
	centroids = []
	global n
	n = len(graph) - 1
	dfs(1, -1)
	return centroids

def link_cut_centroids(g):
	global graph
	graph = g
	if len(graph) % 2 == 0:
		stdout.write('{} {}\n'.format(1, graph[1][0]))
		stdout.write('{} {}\n'.format(1, graph[1][0]))
	else:
		ans = compute_centroids()
		if len(ans) == 1:
			stdout.write('{} {}\n'.format(ans[0][1], ans[0][2]))
			stdout.write('{} {}\n'.format(ans[0][1], ans[0][2]))
		elif len(ans) == 2:
			stdout.write('{} {}\n'.format(ans[0][1], ans[0][2]))
			stdout.write('{} {}\n'.format(ans[0][2], ans[1][0]))

def main_method():
	t = int(stdin.readline())
	for _ in range(t):
		n = int(stdin.readline())
		g = [0] * (n + 1)
		for i in range(n - 1):
			(x, y) = map(int, stdin.readline().split())
			try:
				g[x].append(y)
			except:
				g[x] = [y]
			try:
				g[y].append(x)
			except:
				g[y] = [x]
		link_cut_centroids(g)
threading.Thread(target=main_method).start()


import sys
input = lambda : sys.stdin.readline().rstrip()
from collections import deque
T = int(input())
for _ in range(T):
	N = int(input())
	X = [[] for i in range(N)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		X[x - 1].append(y - 1)
		X[y - 1].append(x - 1)
	P = [-1] * N
	Q = deque([0])
	R = []
	while Q:
		i = deque.popleft(Q)
		R.append(i)
		for a in X[i]:
			if a != P[i]:
				P[a] = i
				X[a].remove(i)
				deque.append(Q, a)
	S = [1] * N
	for i in R[1:][::-1]:
		S[P[i]] += S[i]
	i = 0
	f = 0
	while 1:
		for j in X[i]:
			if 2 * S[j] < N:
				continue
			if 2 * S[j] > N:
				i = j
				break
			v = j
			while len(X[v]):
				v = X[v][0]
			print(v + 1, P[v] + 1)
			print(v + 1, i + 1)
			f = 1
			break
		else:
			print(1, X[0][0] + 1)
			print(1, X[0][0] + 1)
			break
		if f:
			break


import sys
import threading
from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc
input = sys.stdin.readline
t = int(input())

def add_arr_dict(graph, key, value):
	if key in graph:
		graph[key].append(value)
	else:
		graph[key] = [value]
for _ in range(t):
	n = int(input())
	graph = {}
	dummy_edge = None
	for _ in range(n - 1):
		arr = sorted([int(n) for n in input().split(' ')])
		add_arr_dict(graph, arr[0], arr[1])
		add_arr_dict(graph, arr[1], arr[0])
		dummy_edge = (arr[0], arr[1])
	sizes = {}

	@bootstrap
	def size(i):
		if i in sizes:
			return sizes[i]
		res = 1
		sizes[i] = 0
		for j in graph.get(i, []):
			if j not in sizes:
				yield size(j)
				res += sizes[j]
		sizes[i] = res
		yield
	try:
		size(1)
	except Exception:
		pass

	def is_centroid(i):
		size_of_children = [sizes[c] for c in graph.get(i, []) if sizes[c] < sizes[i]]
		max_child = 0 if len(size_of_children) == 0 else max(size_of_children)
		max_parent = n - (1 + sum(size_of_children))
		res = max_child <= n // 2 and max_parent <= n // 2
		return res
	centroid_a = -1
	centroid_b = -1
	for i in range(1, n + 1):
		if is_centroid(i):
			assert centroid_b == -1
			if centroid_a == -1:
				centroid_a = i
			else:
				centroid_b = i
	if centroid_b == -1:
		print('%s %s' % (dummy_edge[0], dummy_edge[1]))
		print('%s %s' % (dummy_edge[0], dummy_edge[1]))
		continue
	edges = [(centroid_b, v) for v in graph[centroid_b] if v != centroid_a]
	edge = edges[0]
	print('%s %s' % (edge[0], edge[1]))
	print('%s %s' % (edge[1], centroid_a))


import sys
import threading

def findCentroids(v, visited, G, level, centroid, parent, size):
	visited[v] = True
	sizeMax = 0
	for u in G[v]:
		if not visited[u]:
			level[u] = level[v] + 1
			parent[u] = v
			findCentroids(u, visited, G, level, centroid, parent, size)
			size[v] += size[u]
			sizeMax = max(sizeMax, size[u])
	sizeMax = max(len(G) - size[v], sizeMax)
	if sizeMax <= len(G) / 2:
		centroid.append(v)

def findLeaf(v, vis, G):
	vis[v] = True
	child = 0
	for u in G[v]:
		if not vis[u]:
			child += 1
			return findLeaf(u, vis, G)
	if child == 0:
		return v

def solve(G):
	visited = [False] * len(G)
	level = [0] * len(G)
	size = [1] * len(G)
	parent = [0] * len(G)
	centroid = []
	findCentroids(0, visited, G, level, centroid, parent, size)
	if len(centroid) == 1:
		print(centroid[0] + 1, G[centroid[0]][0] + 1)
		print(centroid[0] + 1, G[centroid[0]][0] + 1)
	else:
		c1 = centroid[0]
		c2 = centroid[1]
		if level[c1] < level[c2]:
			(c1, c2) = (c2, c1)
		vis = [False] * len(G)
		vis[parent[c1]] = True
		leaf = findLeaf(c1, vis, G)
		print(parent[leaf] + 1, leaf + 1)
		print(c2 + 1, leaf + 1)

def main():
	for _ in range(int(input())):
		n = int(input())
		G = [[] for _ in range(n)]
		for _ in range(n - 1):
			(x, y) = [int(item) - 1 for item in input().split()]
			G[x].append(y)
			G[y].append(x)
		solve(G)
max_recur_size = 10 ** 5 * 2 + 1000
max_stack_size = max_recur_size * 500
sys.setrecursionlimit(max_recur_size)
threading.stack_size(max_stack_size)
thread = threading.Thread(target=main)
thread.start()


from collections import Counter
from collections import deque
from sys import stdin
from bisect import *
from heapq import *
import math
g = lambda : stdin.readline().strip()
gl = lambda : g().split()
gil = lambda : [int(var) for var in gl()]
gfl = lambda : [float(var) for var in gl()]
gcl = lambda : list(g())
gbs = lambda : [int(var) for var in g()]
mod = int(1000000000.0) + 7
inf = float('inf')
(t,) = gil()
for _ in range(t):
	(n,) = gil()
	adj = [[] for _ in range(n + 1)]
	moreThanOne = False
	for _ in range(n - 1):
		(x, y) = gil()
		adj[x].append(y)
		adj[y].append(x)
	root = 1
	d = [1] * (n + 1)
	vis = [0] * (n + 1)
	fin = [0] * (n + 1)
	dfs = [1]
	while dfs:
		if vis[dfs[-1]]:
			p = dfs.pop()
			for c in adj[p]:
				if fin[c]:
					d[p] += d[c]
			fin[p] = 1
			moreThanOne |= True if n - d[p] == d[p] else False
		else:
			vis[dfs[-1]] = 1
			for c in adj[dfs[-1]]:
				if vis[c] == 0:
					dfs.append(c)
	if moreThanOne:
		c = d.index(n // 2)
		for p in adj[c]:
			if d[p] > d[c]:
				break
		l = c
		while d[l] != 1:
			for o in adj[l]:
				if d[o] < d[l]:
					l = o
					break
		lp = adj[l][0]
		print(lp, l)
		print(p, l)
	else:
		print(x, y)
		print(x, y)


from __future__ import division, print_function
import os
import sys, math
from io import BytesIO, IOBase
from itertools import permutations, combinations
from collections import defaultdict, deque, OrderedDict, Counter
from os import path
import random
import bisect as bi
from types import GeneratorType

def yes():
	print('YES')

def no():
	print('NO')

def I():
	return int(input())

def In():
	return map(int, input().split())

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

@bootstrap
def dfs(d, n, visit, dp, s, ans):
	visit[s] = True
	total = []
	t = 0
	for x in d[s]:
		if visit[x] == False:
			temp = (yield dfs(d, n, visit, dp, x, ans))
			total.append(temp)
			t += total[-1]
	flag = 0
	for x in total:
		if x > n // 2:
			flag = 1
			break
	if flag == 0:
		if n - t - 1 <= n // 2:
			ans.append(s)
	dp[s] = t
	yield (dp[s] + 1)

def dfs1(d, n, s, op):
	visit = [False for x in range(n + 1)]
	parent = [0 for x in range(n + 1)]
	q = deque([s])
	while q:
		t = q.popleft()
		z = 0
		for x in d[t]:
			if visit[x] == False and x != op:
				q.appendleft(x)
				parent[x] = t
				z = 1
		visit[t] = True
		if z == 0:
			return [t, parent[t]]

def main():
	try:
		n = I()
		d = defaultdict(list)
		for x in range(n - 1):
			(a, b) = In()
			d[a].append(b)
			d[b].append(a)
		visit = [False for x in range(n + 1)]
		dp = [0 for x in range(n + 1)]
		ans = []
		dfs(d, n, visit, dp, 1, ans)
		if len(ans) == 1:
			print(ans[0], d[ans[0]][0])
			print(ans[0], d[ans[0]][0])
		else:
			an = dfs1(d, n, ans[0], ans[1])
			print(*an)
			print(an[0], ans[1])
	except:
		pass
M = 998244353
P = 1000000007
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
for _ in range(I()):
	main()


import sys
input = sys.stdin.readline

class Graph(object):

	def __init__(self, n, d):
		self.n = n
		self.graph = [[] for i in range(n)]
		self.parent = [-1 for i in range(n)]
		self.directed = d

	def addEdge(self, x, y):
		self.graph[x].append(y)
		if not self.directed:
			self.graph[y].append(x)

	def bfs(self, root):
		queue = [root]
		queue = deque(queue)
		vis = [0] * self.n
		while len(queue) != 0:
			element = queue.popleft()
			vis[element] = 1
			for i in self.graph[element]:
				if vis[i] == 0:
					queue.append(i)
					self.parent[i] = element
					vis[i] = 1

	def dfs(self, root):
		ans = [0] * n
		stack = [root]
		vis = [0] * self.n
		stack2 = []
		while len(stack) != 0:
			element = stack.pop()
			if vis[element]:
				continue
			vis[element] = 1
			stack2.append(element)
			for i in self.graph[element]:
				if vis[i] == 0:
					self.parent[i] = element
					stack.append(i)
		node = -1
		while len(stack2) != 0:
			element = stack2.pop()
			m = 0
			for i in self.graph[element]:
				if i != self.parent[element]:
					m += ans[i]
			ans[element] = m + 1
			if ans[element] == self.n // 2:
				node = element
				break
		return (node, self.parent)

	def shortestpath(self, source, dest):
		self.bfs(source)
		path = [dest]
		while self.parent[path[-1]] != -1:
			path.append(parent[path[-1]])
		return path[::-1]

	def detect_cycle(self):
		indeg = [0] * self.n
		for i in range(self.n):
			for j in self.graph[i]:
				indeg[j] += 1
		q = deque()
		vis = 0
		for i in range(self.n):
			if indeg[i] == 0:
				q.append(i)
		while len(q) != 0:
			e = q.popleft()
			vis += 1
			for i in self.graph[e]:
				indeg[i] -= 1
				if indeg[i] == 0:
					q.append(i)
		if vis != self.n:
			return True
		return False

	def reroot(self, root, ans):
		stack = [root]
		vis = [0] * n
		while len(stack) != 0:
			e = stack[-1]
			if vis[e]:
				stack.pop()
				continue
			vis[e] = 1
			for i in graph[e]:
				if not vis[e]:
					stack.append(i)
			if self.parent[e] == -1:
				continue

	def eulertour(self, root):
		stack = [root]
		t = []
		while len(stack) != 0:
			element = stack[-1]
			if vis[element]:
				t.append(stack.pop())
				continue
			t.append(element)
			vis[element] = 1
			for i in self.graph[element]:
				if not vis[i]:
					stack.append(i)
		return t
for nt in range(int(input())):
	n = int(input())
	g = Graph(n, False)
	for i in range(n - 1):
		(a, b) = map(int, input().split())
		edge = [a, b]
		g.addEdge(a - 1, b - 1)
	if n % 2:
		print(edge[0], edge[1])
		print(edge[0], edge[1])
		continue
	(node, parent) = g.dfs(0)
	if node == -1:
		print(edge[0], edge[1])
		print(edge[0], edge[1])
	elif g.graph[node][1] == parent[node]:
		print(node + 1, g.graph[node][0] + 1)
		print(parent[node] + 1, g.graph[node][0] + 1)
	else:
		print(node + 1, g.graph[node][1] + 1)
		print(parent[node] + 1, g.graph[node][1] + 1)


import sys, os, io
input = sys.stdin.readline
sys.setrecursionlimit(10 ** 6)
T = int(input())

def dfs(start):
	stack = [start]
	visited = [False] * N
	visited[start] = True
	cnts = [-1] * N
	while stack:
		v = stack[-1]
		ans = cnt = marker = 0
		for u in edge[v]:
			if visited[u] == False:
				marker = 1
				visited[u] = True
				stack.append(u)
			elif cnts[u] > -1:
				ans = max(ans, cnts[u])
				cnt += cnts[u]
		if marker == 0:
			cnts[v] = cnt + 1
			ans = max(ans, N - 1 - cnt)
			if ans == N // 2:
				lis.append(v)
			stack.pop()
	return
for t in range(T):
	N = int(input())
	edge = [[] for _ in range(N)]
	for i in range(N - 1):
		(a, b) = map(int, input().split())
		if i == 0:
			edges = [a, b]
		edge[a - 1].append(b - 1)
		edge[b - 1].append(a - 1)
	if N % 2 == 1:
		print(*edges)
		print(*edges)
	else:
		lis = []
		dfs(0)
		if len(lis) <= 1:
			print(*edges)
			print(*edges)
		else:
			for l in edge[lis[0]]:
				if l != lis[1]:
					print(lis[0] + 1, l + 1)
					print(lis[1] + 1, l + 1)
					break


import sys
from collections import deque
input = sys.stdin.readline
for _ in range(int(input())):
	n = int(input())
	edge = [[] for i in range(n)]
	for i in range(n - 1):
		(x, y) = map(int, input().split())
		edge[x - 1].append(y - 1)
		edge[y - 1].append(x - 1)
	size = [1 for i in range(n)]
	parent = [-1 for i in range(n)]
	deq = deque([0])
	res = []
	while deq:
		v = deq.popleft()
		res.append(v)
		for nv in edge[v]:
			if nv != parent[v]:
				parent[nv] = v
				deq.append(nv)
	res = res[::-1]
	for v in res:
		for nv in edge[v]:
			if nv != parent[v]:
				size[v] += size[nv]
	min_size = [n - size[i] for i in range(n)]
	for v in range(n):
		for nv in edge[v]:
			if nv != parent[v]:
				min_size[v] = max(min_size[v], size[nv])
	m = min(min_size)
	(x1, y1) = (-1, -1)
	for v in range(n):
		if min_size[v] == m:
			x1 = v
			for nv in edge[v]:
				if min_size[nv] == m:
					y1 = nv
					break
			else:
				print(x1 + 1, edge[x1][0] + 1)
				print(x1 + 1, edge[x1][0] + 1)
				break
			for nv in edge[y1]:
				if nv != x1:
					print(nv + 1, y1 + 1)
					print(nv + 1, x1 + 1)
					break
			break


from sys import setrecursionlimit
setrecursionlimit(10 ** 9)
import threading
threading.stack_size(67108864)

def dfs(u):
	global n
	used[u] = True
	for to in graf[u]:
		if not used[to]:
			dfs(to)
			size[u] += size[to]
			max_comp[u] = max(max_comp[u], size[to])
	size[u] += 1
	max_comp[u] = max(max_comp[u], n - size[u])

def main():
	global used, n, max_comp, size, graf
	for __ in range(int(input())):
		n = int(input())
		graf = [[] for _ in range(n)]
		for _ in range(n - 1):
			(x, y) = [int(x) for x in input().split()]
			x -= 1
			y -= 1
			graf[x].append(y)
			graf[y].append(x)
		used = [False for _ in range(n)]
		max_comp = [0 for _ in range(n)]
		size = [0 for _ in range(n)]
		dfs(0)
		min_comp = min(max_comp)
		centroids = []
		for u in range(n):
			if max_comp[u] == min_comp:
				centroids.append(u)
		if len(centroids) <= 1:
			print(1, graf[0][0] + 1)
			print(1, graf[0][0] + 1)
		else:
			for to in graf[centroids[0]]:
				if to != centroids[1]:
					break
			print(centroids[0] + 1, to + 1)
			print(centroids[1] + 1, to + 1)
thread = threading.Thread(target=main)
thread.start()
thread.join()


def get_leaf(s, links):
	q = [s]
	while q:
		v = q.pop()
		if len(links[v]) == 0:
			return v
		for u in links[v]:
			q.append(u)

def solve(n, links):
	q = [(0, -1)]
	subtree_size = [-1] * n
	parents = [-1] * n
	limit = (n + 1) // 2
	v = -1
	while q:
		(v, p) = q.pop()
		if p == -2:
			tmp = 1
			for u in links[v]:
				tmp += subtree_size[u]
			subtree_size[v] = tmp
			if tmp >= limit:
				break
		else:
			links[v].discard(p)
			parents[v] = p
			q.append((v, -2))
			for u in links[v]:
				q.append((u, v))
	if v == 0:
		u = links[v].pop()
		return ((v, u), (v, u))
	p = parents[v]
	if n % 2 == 1:
		return ((v, p), (v, p))
	if subtree_size[v] > limit:
		return ((v, p), (v, p))
	u = get_leaf(v, links)
	return ((u, parents[u]), (u, p))
t = int(input())
buf = []
for _ in range(t):
	n = int(input())
	links = [set() for _ in range(n)]
	for _ in range(n - 1):
		(x, y) = map(int, input().split())
		x -= 1
		y -= 1
		links[x].add(y)
		links[y].add(x)
	((u, v), (w, z)) = solve(n, links)
	buf.append(f'{u + 1} {v + 1}\n')
	buf.append(f'{w + 1} {z + 1}\n')
print(''.join(buf))


import sys, math
import io, os
from bisect import bisect_left as bl, bisect_right as br, insort
from heapq import heapify, heappush, heappop
from collections import defaultdict as dd, deque, Counter

def data():
	return sys.stdin.readline().strip()

def mdata():
	return list(map(int, data().split()))

def outl(var):
	sys.stdout.write(' '.join(map(str, var)) + '\n')

def out(var):
	sys.stdout.write(str(var) + '\n')
from decimal import Decimal
mod = int(1000000000.0) + 7
INF = float('inf')

def dfs(graph, start=0):
	n = len(graph)
	dp = [0] * n
	(visited, finished) = ([False] * n, [False] * n)
	par = [0] * n
	stack = [start]
	while stack:
		start = stack[-1]
		if not visited[start]:
			visited[start] = True
			for child in graph[start]:
				if not visited[child]:
					par[child] = start
					stack.append(child)
		else:
			stack.pop()
			dp[start] += 1
			for child in graph[start]:
				if finished[child]:
					dp[start] += dp[child]
			finished[start] = True
	return (dp, par)
for t in range(int(data())):
	n = int(data())
	graph = [[] for i in range(n)]
	for i in range(n - 1):
		(x, y) = mdata()
		graph[x - 1].append(y - 1)
		graph[y - 1].append(x - 1)
	d = dd(list)
	(dp, par) = dfs(graph)
	for i in range(n):
		if i == 0:
			m = 0
			for j in graph[i]:
				m = max(m, dp[j])
		else:
			m = 0
			for j in graph[i]:
				if j != par[i]:
					m = max(m, dp[j])
			m = max(m, dp[0] - dp[i])
		d[m].append(i)
	if len(d[min(d.keys())]) == 1:
		print(1, graph[0][0] + 1)
		print(1, graph[0][0] + 1)
	else:
		(a, b) = d[min(d.keys())]
		if graph[a][0] != b:
			print(a + 1, graph[a][0] + 1)
			print(b + 1, graph[a][0] + 1)
		else:
			print(a + 1, graph[a][1] + 1)
			print(b + 1, graph[a][1] + 1)


import sys
from functools import lru_cache, cmp_to_key
from heapq import merge, heapify, heappop, heappush, nsmallest
from math import ceil, floor, gcd, fabs, factorial, fmod, sqrt, inf
from collections import defaultdict as dd, deque, Counter as C
from itertools import combinations as comb, permutations as perm
from bisect import bisect_left as bl, bisect_right as br, bisect
from time import perf_counter
from fractions import Fraction
from decimal import Decimal
from types import GeneratorType
mod = pow(10, 9) + 7

def data():
	return sys.stdin.readline().strip()

def out(var):
	sys.stdout.write(str(var) + '\n')

def outa(*var, end='\n'):
	sys.stdout.write(' '.join(map(str, var)) + end)

def l():
	return list(sp())

def sl():
	return list(ssp())

def sp():
	return map(int, data().split())

def ssp():
	return map(str, data().split())

def l1d(n, val=0):
	return [val for i in range(n)]

def l2d(n, m, val=0):
	return [l1d(n, val) for j in range(m)]

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

@bootstrap
def dfs(source=0, parent=-1):
	size[source] += 1
	for child in tree[source]:
		if child != parent:
			size[source] += (yield dfs(child, source))
			par[child] = source
	yield size[source]

def dfs2(source, parent):
	q = [[source, parent]]
	while q:
		(s, p) = q.pop()
		for child in tree[s]:
			if child == p:
				continue
			if len(tree[child]) == 1:
				return child
			q.append([child, s])
	return 0
for _ in range(int(data())):
	n = int(data())
	tree = [list() for i in range(n)]
	for i in range(n - 1):
		(x, y) = sp()
		x -= 1
		y -= 1
		tree[x].append(y)
		tree[y].append(x)
	if n & 1:
		for child in tree[0]:
			outa(1, child + 1)
			outa(1, child + 1)
			break
		continue
	found = -1
	size = [0] * n
	par = [0] * n
	dfs()
	for i in range(1, n):
		if size[i] == n // 2:
			found = i
			break
	if found == -1:
		for child in tree[0]:
			outa(1, child + 1)
			outa(1, child + 1)
			break
		continue
	leaf = dfs2(found, par[found])
	outa(leaf + 1, par[leaf] + 1)
	outa(leaf + 1, par[found] + 1)


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	n = int(input())
	dic = {}
	dis = {}
	people = {}
	dico = {}
	for i in range(1, n + 1):
		dic[i] = []
		dis[i] = 0
		dico[i] = []
		people[i] = -1
	for i in range(n - 1):
		(x, y) = map(int, input().split())
		dic[x].append(y)
		dic[y].append(x)
		dico[x].append(y)
		dico[y].append(x)
	dis[1] = 0
	level = 1
	se = {1}
	ne = set({1})
	while ne:
		tem = set({})
		for i in ne:
			xx = dic[i]
			for j in xx:
				if not j in se:
					se.add(j)
					dis[j] = level
					tem.add(j)
		ne = tem.copy()
		level += 1
	for i in dic:
		dic[i].sort(key=lambda x: dis[x])
	st = 1
	se = {1}
	people[st] = 0
	while dic[st]:
		ne = dic[st].pop()
		if not ne in se:
			people[ne] = 0
			se.add(ne)
			people[ne] = 0
		else:
			people[ne] += people[st] + 1
		st = ne
	val = [0] * n
	st = {1}
	ne = {1}
	se = {1}
	while ne:
		tem = set({})
		for i in ne:
			xx = dico[i]
			meas = []
			for j in xx:
				if not j in se:
					se.add(j)
					tem.add(j)
					meas.append(people[j] + 1)
			meas.append(n - sum(meas) - 1)
			val[i - 1] = max(meas)
		ne = tem.copy()
	mi = min(val)
	if val.count(mi) < 2:
		xx = []
		for i in dico[1]:
			xx.append(i)
			break
		print(1, i)
		print(1, i)
	else:
		xxx = []
		for i in range(n):
			if val[i] == mi:
				xxx.append(i + 1)
		xxx.sort(key=lambda x: dis[x], reverse=True)
		st = {xxx[0]}
		ne = {xxx[0]}
		di = dis[xxx[0]]
		req = []
		flag = True
		while ne and flag:
			tem = set({})
			for i in ne:
				stem = set({})
				xx = dico[i]
				for j in xx:
					if dis[j] > di:
						tem.add(j)
						stem.add(j)
				if not stem:
					flag = False
					req = [i, j]
					break
			ne = tem.copy()
			di += 1
		print(*req)
		print(xxx[1], req[0])


import io, os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
from collections import defaultdict, deque
t = int(input())
for _ in range(t):
	n = int(input())
	adj = defaultdict(list)
	edges_list = []
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		adj[u].append(v)
		adj[v].append(u)
		edges_list.append((u, v))
	size = [0] * (n + 1)
	parents = [0] * (n + 1)
	states = []
	q = deque([[1, -1]])
	while q:
		(e, p) = q.popleft()
		states.append(e)
		parents[e] = p
		for i in adj[e]:
			if i != p:
				q.append([i, e])
	for i in range(n, 0, -1):
		for j in adj[states[i - 1]]:
			if states[i - 1] == parents[j]:
				size[states[i - 1]] += 1 + size[j]
	centroids = []
	min_centroid = 10 ** 18
	for i in range(1, 1 + n):
		max_size = 0
		for j in adj[i]:
			if parents[j] == i:
				max_size = max(max_size, size[j] + 1)
			else:
				max_size = max(max_size, n - size[i] - 1)
		if max_size < min_centroid:
			centroids = [i]
			min_centroid = min(min_centroid, max_size)
		elif max_size == min_centroid:
			centroids.append(i)
	centroids = list(set(centroids))
	if len(centroids) == 1:
		print(*(centroids[0], adj[centroids[0]][0]))
		print(*(centroids[0], adj[centroids[0]][0]))
	else:
		second = 0
		for j in adj[centroids[0]]:
			if j != centroids[1]:
				second = j
				break
		print(centroids[0], second)
		print(centroids[1], second)


import sys
readline = sys.stdin.readline
INF = 1 << 60

def read_int():
	return int(readline())

def read_int_n():
	return list(map(int, readline().split()))

def read_float():
	return float(readline())

def read_float_n():
	return list(map(float, readline().split()))

def read_str():
	return readline().strip()

def read_str_n():
	return readline().strip().split()

def ep(*args):
	print(*args, file=sys.stderr)

def mt(f):
	import time

	def wrap(*args, **kwargs):
		s = time.perf_counter()
		ret = f(*args, **kwargs)
		e = time.perf_counter()
		ep(e - s, 'sec')
		return ret
	return wrap
from collections import defaultdict, Counter, deque
from functools import lru_cache

def slv(N, XY):
	g = defaultdict(set)
	r = Counter()
	for (x, y) in XY:
		g[x].add(y)
		g[y].add(x)
	memo = defaultdict(dict)

	def dfs(u, p):
		if u in memo and p in memo[u]:
			return memo[u][p]
		bu = u
		bp = p
		o = []
		s = [(u, p)]
		while s:
			(u, p) = s.pop()
			if u in memo and p in memo[u]:
				continue
			o.append((u, p))
			for v in g[u]:
				if v == p:
					continue
				s.append((v, u))
		o.reverse()
		for (u, p) in o:
			r = 1
			for v in g[u]:
				if v == p:
					continue
				r += memo[v][u]
			memo[u][p] = r
		return memo[bu][bp]
	for u in range(1, N + 1):
		n = 0
		for v in g[u]:
			n = max(n, dfs(v, u))
		r[u] = n
	(a, b) = r.most_common(n=N)[-2:]
	if a[1] != b[1]:
		print(a[0], b[0])
		print(a[0], b[0])
	else:
		u = a[0]
		v = b[0]
		c = (-INF, -1)
		for vv in g[u]:
			c = max(c, (r[vv], vv))
		c = c[1]
		print(u, c)
		print(c, v)

def main():
	for _ in range(read_int()):
		N = read_int()
		XY = [read_int_n() for _ in range(N - 1)]
		slv(N, XY)
main()


import sys
import math as mt
import collections as cc
import bisect as bi
input = sys.stdin.readline
I = lambda : list(map(int, input().split()))
for tc in range(int(input())):
	(n,) = I()
	g = cc.defaultdict(list)
	for i in range(n - 1):
		(x, y) = I()
		g[x].append(y)
		g[y].append(x)
	par = [0] * (n + 1)
	odr = []
	st = cc.deque()
	st.append(1)
	visi = [0] * (n + 1)
	while st:
		x = st.pop()
		visi[x] = 1
		odr.append(x)
		for y in g[x]:
			if not visi[y]:
				visi[y] = 1
				par[y] = x
				st.append(y)
	child = [1] * (n + 1)
	cnt = [0] * (n + 1)
	for i in odr[1:][::-1]:
		child[par[i]] += child[i]
		cnt[par[i]] = max(cnt[par[i]], child[i])
	for i in range(1, n + 1):
		cnt[i] = max(cnt[i], n - child[i])
	now = min(cnt[1:])
	ccnt = []
	for i in range(1, n + 1):
		if cnt[i] == now:
			ccnt.append(i)
	if len(ccnt) == 1:
		print(1, g[1][0])
		print(1, g[1][0])
	else:
		(o, p) = ccnt
		for i in g[o]:
			if i != p:
				an = i
				break
		print(o, i)
		print(p, i)


import sys
from collections import deque
input = sys.stdin.buffer.readline

def main():
	t = int(input())
	for tt in range(t):
		n = int(input())
		v = [[] for i in range(n + 1)]
		z = [1] * (n + 1)
		for i in range(n - 1):
			(a, b) = map(int, input().split())
			v[a].append(b)
			v[b].append(a)
		q = deque()
		q.append(1)
		vis = [-1] * (n + 1)
		pr = [-1] * (n + 1)
		c = [[] for i in range(n + 1)]
		vis[1] = 0
		rec = []
		while q:
			u = q.popleft()
			rec.append(u)
			for i in v[u]:
				if vis[i] == -1:
					vis[i] = vis[u] + 1
					pr[i] = u
					q.append(i)
					c[u].append(i)
		rec.reverse()
		a = 0
		b = 0
		for i in rec:
			for j in c[i]:
				z[i] += z[j]
				if z[j] * 2 == n:
					a = j
		if a == b:
			print(pr[2], 2)
			print(pr[2], 2)
		else:
			b = pr[a]
			for j in v[a]:
				if b != j:
					print(a, j)
					print(j, b)
					break
main()


from collections import defaultdict, Counter, deque
from operator import add
from functools import lru_cache
import sys
readline = sys.stdin.readline
INF = 1 << 60

def read_int():
	return int(readline())

def read_int_n():
	return list(map(int, readline().split()))

def read_float():
	return float(readline())

def read_float_n():
	return list(map(float, readline().split()))

def read_str():
	return readline().strip()

def read_str_n():
	return readline().strip().split()

def ep(*args):
	print(*args, file=sys.stderr)

def mt(f):
	import time

	def wrap(*args, **kwargs):
		s = time.perf_counter()
		ret = f(*args, **kwargs)
		e = time.perf_counter()
		ep(e - s, 'sec')
		return ret
	return wrap

class ReRooting:

	def __init__(self, f, g, merge, ie):
		self.tree = defaultdict(list)
		self.f = f
		self.g = g
		self.merge = merge
		self.ie = ie
		self.dp = defaultdict(dict)

	def add_edge(self, u, v):
		self.tree[u].append(v)
		self.tree[v].append(u)

	def __dfs1(self, u, p):
		o = []
		s = [(u, -1)]
		while s:
			(u, p) = s.pop()
			o.append((u, p))
			for v in self.tree[u]:
				if v == p:
					continue
				s.append((v, u))
		for (u, p) in reversed(o):
			r = self.ie
			for v in self.tree[u]:
				if v == p:
					continue
				r = self.merge(r, self.f(self.dp[u][v], v))
			self.dp[p][u] = self.g(r, u)

	def __dfs2(self, u, p, a):
		s = [(u, p, a)]
		while s:
			(u, p, a) = s.pop()
			self.dp[u][p] = a
			pl = [0] * (len(self.tree[u]) + 1)
			pl[0] = self.ie
			for (i, v) in enumerate(self.tree[u]):
				pl[i + 1] = self.merge(pl[i], self.f(self.dp[u][v], v))
			pr = [0] * (len(self.tree[u]) + 1)
			pr[-1] = self.ie
			for (i, v) in reversed(list(enumerate(self.tree[u]))):
				pr[i] = self.merge(pr[i + 1], self.f(self.dp[u][v], v))
			for (i, v) in enumerate(self.tree[u]):
				if v == p:
					continue
				r = self.merge(pl[i], pr[i + 1])
				s.append((v, u, self.g(r, v)))

	def build(self, root=1):
		self.__dfs1(root, -1)
		self.__dfs2(root, -1, self.ie)

	def slv(self, u):
		r = 0
		for v in self.tree[u]:
			r = max(r, self.dp[u][v])
		return r

def slv(N, XY):

	def f(x, _):
		return x

	def g(x, _):
		return x + 1
	merge = add
	ie = 0
	g = ReRooting(f, g, merge, ie)
	for (x, y) in XY:
		g.add_edge(x, y)
	g.build()
	r = Counter()
	for u in range(1, N + 1):
		r[u] = g.slv(u)
	(a, b) = r.most_common(n=N)[-2:]
	if a[1] != b[1]:
		print(a[0], b[0])
		print(a[0], b[0])
	else:
		u = a[0]
		v = b[0]
		c = (-INF, -1)
		for vv in g.tree[u]:
			c = max(c, (r[vv], vv))
		c = c[1]
		print(u, c)
		print(c, v)

def main():
	for _ in range(read_int()):
		N = read_int()
		XY = [read_int_n() for _ in range(N - 1)]
		slv(N, XY)
main()


from sys import stdin, stdout
import math, sys, heapq
from itertools import permutations, combinations
from collections import defaultdict, deque, OrderedDict, Counter
from os import path
import random
import bisect as bi
from types import GeneratorType

def yes():
	print('YES')

def no():
	print('NO')
if path.exists('input.txt'):
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')

	def I():
		return int(input())

	def In():
		return map(int, input().split())
else:

	def I():
		return int(stdin.readline())

	def In():
		return map(int, stdin.readline().split())

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

def dict(a):
	d = {}
	for x in a:
		if d.get(x, -1) != -1:
			d[x] += 1
		else:
			d[x] = 1
	return d

def find_gt(a, x):
	i = bi.bisect_left(a, x)
	if i != len(a):
		return i
	else:
		return -1

@bootstrap
def dfs(d, n, visit, dp, s, ans):
	visit[s] = True
	total = []
	t = 0
	for x in d[s]:
		if visit[x] == False:
			temp = (yield dfs(d, n, visit, dp, x, ans))
			total.append(temp)
			t += total[-1]
	flag = 0
	for x in total:
		if x > n // 2:
			flag = 1
			break
	if flag == 0:
		if n - t - 1 <= n // 2:
			ans.append(s)
	dp[s] = t
	yield (dp[s] + 1)

def dfs1(d, n, s, op):
	visit = [False for x in range(n + 1)]
	parent = [0 for x in range(n + 1)]
	q = deque([s])
	while q:
		t = q.popleft()
		z = 0
		for x in d[t]:
			if visit[x] == False and x != op:
				q.appendleft(x)
				parent[x] = t
				z = 1
		visit[t] = True
		if z == 0:
			return [t, parent[t]]

def main():
	try:
		n = I()
		d = defaultdict(list)
		for x in range(n - 1):
			(a, b) = In()
			d[a].append(b)
			d[b].append(a)
		visit = [False for x in range(n + 1)]
		dp = [0 for x in range(n + 1)]
		ans = []
		dfs(d, n, visit, dp, 1, ans)
		if len(ans) == 1:
			print(ans[0], d[ans[0]][0])
			print(ans[0], d[ans[0]][0])
		else:
			an = dfs1(d, n, ans[0], ans[1])
			print(*an)
			print(an[0], ans[1])
	except:
		pass
M = 998244353
P = 1000000007
for _ in range(I()):
	main()


import sys
from collections import deque, defaultdict
input = sys.stdin.buffer.readline
T = int(input())
for _ in range(T):
	n = int(input())
	e = [[] for _ in range(n + 1)]
	for _ in range(n - 1):
		(a, b) = map(int, input().split())
		e[a].append(b)
		e[b].append(a)
	(par, order, q) = ([0] * (n + 1), [], deque([1]))
	while q:
		u = q.popleft()
		order.append(u)
		for v in e[u]:
			if v == par[u]:
				continue
			q.append(v)
			par[v] = u
	(mxcc, ndcc) = (defaultdict(list), [0] * (n + 1))
	for u in reversed(order):
		(cc, sm) = (0, 0)
		for v in e[u]:
			if v == par[u]:
				continue
			cc = max(cc, ndcc[v])
			sm += ndcc[v]
		sm += 1
		cc = max(cc, n - sm)
		mxcc[cc].append(u)
		ndcc[u] = sm
	(_, ls) = min(mxcc.items())
	if len(ls) == 1:
		(u, v) = (ls[0], e[ls[0]][0])
		print(u, v)
		print(u, v)
	else:
		(u, v) = (ls[0], e[ls[0]][0])
		if v == ls[1]:
			v = e[ls[0]][1]
		print(u, v)
		print(v, ls[1])


import sys
import math
import heapq
import bisect
from collections import Counter
from collections import defaultdict
from io import BytesIO, IOBase
from types import GeneratorType
import string

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		import os
		self.os = os
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None
		self.BUFSIZE = 8192

	def read(self):
		while True:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, self.BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, self.BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			self.os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def get_int():
	return int(input())

def get_ints():
	return list(map(int, input().split(' ')))

def get_int_grid(n):
	return [get_ints() for _ in range(n)]

def get_str():
	return input().strip()

def get_strs():
	return get_str().split(' ')

def flat_list(arr):
	return [item for subarr in arr for item in subarr]

def yes_no(b):
	if b:
		return 'YES'
	else:
		return 'NO'

def binary_search(good, left, right, delta=1, right_true=False):
	limits = [left, right]
	while limits[1] - limits[0] > delta:
		if delta == 1:
			mid = sum(limits) // 2
		else:
			mid = sum(limits) / 2
		if good(mid):
			limits[int(right_true)] = mid
		else:
			limits[int(~right_true)] = mid
	if good(limits[int(right_true)]):
		return limits[int(right_true)]
	else:
		return False

def prefix_sums(a):
	p = [0]
	for x in a:
		p.append(p[-1] + x)
	return p

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

def solve_a():
	n = get_int()
	a = get_ints()
	ans = 0
	for i in range(n + 1):
		if a.count(i) < 2:
			ans += i
			break
	for i in range(n + 1):
		if a.count(i) < 1:
			ans += i
			break
	return ans

def solve_b():
	n = get_int()
	a = get_ints()
	a.sort()
	x = []
	x.append(a[0] * a[1] * a[2] * a[3] * a[-1])
	x.append(a[0] * a[1] * a[-3] * a[-2] * a[-1])
	x.append(a[-5] * a[-4] * a[-3] * a[-2] * a[-1])
	return max(x)

def centroid(T):
	n = len(T)
	sz = [0] * n
	centroid = []
	vis = [False] * n

	@bootstrap
	def dfs(u):
		vis[u] = True
		sz[u] = 1
		is_centroid = True
		for v in T[u]:
			if vis[v]:
				continue
			yield dfs(v)
			sz[u] += sz[v]
			if sz[v] > n / 2:
				is_centroid = False
		if n - sz[u] > n / 2:
			is_centroid = False
		if is_centroid:
			centroid.append(u)
		yield
	dfs(0)
	return centroid

def get_tree():
	n = get_int()
	T = [[] for _ in range(n)]
	for _ in range(n - 1):
		(a, b) = get_ints()
		a -= 1
		b -= 1
		T[a].append(b)
		T[b].append(a)
	return T

def solve_c():
	T = get_tree()
	c = centroid(T)
	if len(c) == 1:
		edge = (c[0] + 1, T[c[0]].pop() + 1)
		return (edge, edge)
	elif len(c) == 2:
		vis = [False] * len(T)
		vis[c[0]] = True
		leafs = []

		@bootstrap
		def dfs2(u):
			if len(T[u]) == 1:
				leafs.append(u)
				yield
			vis[u] = True
			for v in T[u]:
				if vis[v]:
					continue
				else:
					yield dfs2(v)
			yield
		dfs2(c[1])
		leaf = leafs[0]
		edge1 = (leaf + 1, T[leaf].pop() + 1)
		edge2 = (leaf + 1, c[0] + 1)
		return (edge1, edge2)
t = get_int()
for _ in range(t):
	ans = solve_c()
	for edge in ans:
		print(*edge)


def solve(G, edges):
	centroids = []
	(mark, pi, size, max_cc) = [[0] * len(G) for _ in range(4)]
	sons = [[] for _ in range(len(G))]
	m = [999999999999999] * 1
	pi[0] = -1
	DFS_VISIT_ITERATIVE(G, 0, mark, pi, sons, size, max_cc, m)
	for i in range(len(G)):
		if max_cc[i] == m[0]:
			centroids.append(i)
	if len(centroids) == 1:
		edges[0] = edges[2] = 1
		edges[1] = edges[3] = G[0][0] + 1
	else:
		father = centroids[1] if pi[centroids[0]] == centroids[1] else centroids[0]
		son = centroids[1] if father == centroids[0] else centroids[0]
		current = son
		while size[current] != 0:
			current = sons[current][0]
		edges[0] = pi[current] + 1
		edges[1] = edges[3] = current + 1
		edges[2] = father + 1
	return

def DFS_VISIT(G, u, mark, pi, sons, size, max_cc, m):
	mark[u] = 1
	for i in range(len(G[u])):
		if mark[G[u][i]] == 0:
			pi[G[u][i]] = u
			sons[u].append(G[u][i])
			DFS_VISIT(G, G[u][i], mark, pi, sons, size, max_cc, m)
			size[u] += size[G[u][i]] + 1
	for i in range(len(G[u])):
		max_cc[u] = max(max_cc[u], size[G[u][i]] + 1, len(G) - (size[u] + 1))
	m[0] = min(m[0], max_cc[u])

def DFS_VISIT_ITERATIVE(G, u, mark, pi, son, size, max_cc, m):
	current = u
	while current != -1:
		mark[current] = 1
		done = 1
		for i in range(len(G[current])):
			if mark[G[current][i]] == 0:
				done = 0
				pi[G[current][i]] = current
				son[current].append(G[current][i])
				current = G[current][i]
				break
		if done == 1:
			for i in range(len(G[current])):
				max_cc[current] = max(max_cc[current], size[G[current][i]] + 1, len(G) - (size[current] + 1))
			m[0] = min(m[0], max_cc[current])
			if current != 0:
				size[pi[current]] += size[current] + 1
			current = pi[current]
	return

def main():
	cases = int(input())
	answers = []
	for i in range(0, cases):
		n = int(input())
		e = n - 1
		G = [[] for _ in range(n)]
		for j in range(e):
			(u, v) = [int(d) for d in input().split()]
			G[u - 1].append(v - 1)
			G[v - 1].append(u - 1)
		edges = [0] * 4
		solve(G, edges)
		answers.append(' '.join((str(edges[i]) for i in range(0, 2))))
		answers.append(' '.join((str(edges[i]) for i in range(2, 4))))
	s = '\n'.join((str(i) for i in answers))
	print(s)
main()


import sys
from collections import defaultdict, deque
input = sys.stdin.readline

def bfs(node):
	q = deque([node])
	vis[node] = 1
	rec = []
	while q:
		x = q.popleft()
		rec.append(x)
		for i in edge[x]:
			if vis[i] == 0:
				vis[i] = 1
				c[x].append(i)
				q.append(i)
	rec.reverse()
	return rec
t = int(input())
for _ in range(t):
	n = int(input())
	edge = defaultdict(list)
	arr = []
	for i in range(n - 1):
		(x, y) = list(map(int, input().split()))
		edge[x].append(y)
		edge[y].append(x)
		if i == 0:
			arr.append([x, y])
	subTreeSize = [1] * (n + 1)
	vis = [0] * (n + 1)
	c = defaultdict(list)
	array = bfs(1)
	for i in array:
		for j in c[i]:
			subTreeSize[i] += subTreeSize[j]
	lis = []
	for i in range(1, n + 1):
		maxi = 0
		for j in edge[i]:
			if subTreeSize[j] > subTreeSize[i]:
				maxi = max(maxi, n - subTreeSize[i])
			else:
				maxi = max(subTreeSize[j], maxi)
		lis.append(maxi)
	a = min(lis)
	b = lis.count(a)
	if b == 1:
		print(arr[0][0], arr[0][1])
		print(arr[0][0], arr[0][1])
	else:
		for i in range(n):
			if lis[i] == a:
				i += 1
				break
		for j in range(i, n):
			if lis[j] == a:
				j += 1
				break
		m = 10 ** 9
		mi = -1
		for k in edge[j]:
			if k == i:
				continue
			elif m > subTreeSize[k]:
				m = subTreeSize[k]
				mi = k
		print(j, mi)
		print(i, mi)


from types import GeneratorType
from collections import defaultdict
from sys import stdin
input = stdin.readline

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

@bootstrap
def dfs(x, f):
	global mn, cent1, cent2
	father[x] = f
	size[x] = 1
	mx = 0
	for y in g[x]:
		if y == f:
			continue
		yield dfs(y, x)
		size[x] += size[y]
		mx = max(mx, size[y])
	mx = max(mx, n - size[x])
	if mx < mn:
		mn = mx
		cent1 = x
		cent2 = 0
	elif mx == mn:
		cent2 = x
	yield

@bootstrap
def dfs2(x, f):
	global swap
	if len(g[x]) == 1:
		swap = x
		yield
	for y in g[x]:
		if y == f:
			continue
		yield dfs2(y, x)
	yield
for i in range(int(input())):
	blanck = []
	n = int(input())
	g = defaultdict(list)
	for x in range(n - 1):
		(a, b) = map(int, input().strip().split())
		g[a].append(b)
		g[b].append(a)
	(father, size) = ([0] * (n + 1), [0] * (n + 1))
	mn = 10 ** 9
	(cent1, cent2) = (0, 0)
	dfs(1, 0)
	if cent2 == 0:
		print(1, g[1][0])
		print(1, g[1][0])
		continue
	swap = 0
	if father[cent1] != cent2:
		(cent1, cent2) = (cent2, cent1)
	dfs2(cent1, cent2)
	print(swap, father[swap])
	print(swap, cent2)


import math
import os
from io import BytesIO, IOBase
import sys
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def get_centroids(g):
	n = len(g)
	centroids = []
	sz = [0] * n
	seen = set()
	dfs_queue = [(0, -1)]
	while len(dfs_queue) > 0:
		(u, prev) = dfs_queue[-1]
		sz[u] = 1
		found = False
		for v in g[u]:
			if v != prev and v not in seen:
				dfs_queue.append((v, u))
				found = True
				break
		if found:
			continue
		is_centroid = True
		for v in g[u]:
			if v != prev:
				sz[u] += sz[v]
				if sz[v] > n // 2:
					is_centroid = False
		if n - sz[u] > n // 2:
			is_centroid = False
		if is_centroid:
			centroids.append(u)
		seen.add(u)
		dfs_queue.pop()
	return (centroids, sz)
t = int(input())
for _ in range(t):
	n = int(input())
	adj = [[] for i in range(n)]
	for i in range(n - 1):
		(src, dst) = map(int, input().split())
		src -= 1
		dst -= 1
		adj[src].append(dst)
		adj[dst].append(src)
	(centroids, orig_sz) = get_centroids(adj)
	centroids = list(set(centroids))
	if len(centroids) == 1:
		print(f'1 {adj[0][0] + 1}')
		print(f'1 {adj[0][0] + 1}')
		continue
	adj[centroids[0]].remove(centroids[1])
	adj[centroids[1]].remove(centroids[0])
	(_, sz) = get_centroids(adj)
	if sz[centroids[0]] > 0:
		centroid = centroids[0]
		other = centroids[1]
	else:
		other = centroids[0]
		centroid = centroids[1]
	for (idx, val) in enumerate(sz):
		if idx == other:
			continue
		if val == 0 and orig_sz[idx] == 1:
			print(f'{idx + 1} {adj[idx][0] + 1}')
			print(f'{centroid + 1} {idx + 1}')
			break


from bisect import *
from collections import *
from math import gcd, ceil, sqrt, floor, inf
from heapq import *
from itertools import *
from operator import add, mul, sub, xor, truediv, floordiv
from functools import *
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def RL():
	return map(int, sys.stdin.readline().rstrip().split())

def RLL():
	return list(map(int, sys.stdin.readline().rstrip().split()))

def N():
	return int(input())
farr = [1]
ifa = []

def fact(x, mod=0):
	if mod:
		while x >= len(farr):
			farr.append(farr[-1] * len(farr) % mod)
	else:
		while x >= len(farr):
			farr.append(farr[-1] * len(farr))
	return farr[x]

def ifact(x, mod):
	global ifa
	ifa.append(pow(farr[-1], mod - 2, mod))
	for i in range(x, 0, -1):
		ifa.append(ifa[-1] * i % mod)
	ifa = ifa[::-1]

def per(i, j, mod=0):
	if i < j:
		return 0
	if not mod:
		return fact(i) // fact(i - j)
	return farr[i] * ifa[i - j] % mod

def com(i, j, mod=0):
	if i < j:
		return 0
	if not mod:
		return per(i, j) // fact(j)
	return per(i, j, mod) * ifa[j] % mod

def catalan(n):
	return com(2 * n, n) // (n + 1)

def linc(f, t, l, r):
	while l < r:
		mid = (l + r) // 2
		if t > f(mid):
			l = mid + 1
		else:
			r = mid
	return l

def rinc(f, t, l, r):
	while l < r:
		mid = (l + r + 1) // 2
		if t < f(mid):
			r = mid - 1
		else:
			l = mid
	return l

def ldec(f, t, l, r):
	while l < r:
		mid = (l + r) // 2
		if t < f(mid):
			l = mid + 1
		else:
			r = mid
	return l

def rdec(f, t, l, r):
	while l < r:
		mid = (l + r + 1) // 2
		if t > f(mid):
			r = mid - 1
		else:
			l = mid
	return l

def isprime(n):
	for i in range(2, int(n ** 0.5) + 1):
		if n % i == 0:
			return False
	return True

def binfun(x):
	c = 0
	for w in arr:
		c += ceil(w / x)
	return c

def lowbit(n):
	return n & -n

def inverse(a, m):
	a %= m
	if a <= 1:
		return a
	return (1 - inverse(m, a) * m) // a % m

class BIT:

	def __init__(self, arr):
		self.arr = arr
		self.n = len(arr) - 1

	def update(self, x, v):
		while x <= self.n:
			self.arr[x] += v
			x += x & -x

	def query(self, x):
		ans = 0
		while x:
			ans += self.arr[x]
			x &= x - 1
		return ans

class smt:

	def __init__(self, l, r, arr):
		self.l = l
		self.r = r
		self.value = (1 << 31) - 1 if l < r else arr[l]
		mid = (l + r) // 2
		if l < r:
			self.left = smt(l, mid, arr)
			self.right = smt(mid + 1, r, arr)
			self.value &= self.left.value & self.right.value

	def setvalue(self, x, val):
		if self.l == self.r:
			self.value = val
			return
		mid = (self.l + self.r) // 2
		if x <= mid:
			self.left.setvalue(x, val)
		else:
			self.right.setvalue(x, val)
		self.value = self.left.value & self.right.value

	def ask(self, l, r):
		if l <= self.l and r >= self.r:
			return self.value
		val = (1 << 31) - 1
		mid = (self.l + self.r) // 2
		if l <= mid:
			val &= self.left.ask(l, r)
		if r > mid:
			val &= self.right.ask(l, r)
		return val

class DSU:

	def __init__(self, n):
		self.c = [-1] * n

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def find(self, x):
		if self.c[x] < 0:
			return x
		self.c[x] = self.find(self.c[x])
		return self.c[x]

	def union(self, u, v):
		(u, v) = (self.find(u), self.find(v))
		if u == v:
			return False
		if self.c[u] < self.c[v]:
			(u, v) = (v, u)
		self.c[u] += self.c[v]
		self.c[v] = u
		return True

	def size(self, x):
		return -self.c[self.find(x)]

class UFS:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.ranks = [0] * n

	def find(self, x):
		if x != self.parent[x]:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, u, v):
		(pu, pv) = (self.find(u), self.find(v))
		if pu == pv:
			return False
		if self.ranks[pu] >= self.ranks[pv]:
			self.parent[pv] = pu
			if self.ranks[pv] == self.ranks[pu]:
				self.ranks[pu] += 1
		else:
			self.parent[pu] = pv

def Prime(n):
	c = 0
	prime = []
	flag = [0] * (n + 1)
	for i in range(2, n + 1):
		if not flag[i]:
			prime.append(i)
			c += 1
		for j in range(c):
			if i * prime[j] > n:
				break
			flag[i * prime[j]] = prime[j]
			if i % prime[j] == 0:
				break
	return prime

def dij(s, graph):
	d = {}
	d[s] = 0
	heap = [(0, s)]
	seen = set()
	while heap:
		(dis, u) = heappop(heap)
		if u in seen:
			continue
		for v in graph[u]:
			if v not in d or d[v] > d[u] + graph[u][v]:
				d[v] = d[u] + graph[u][v]
				heappush(heap, (d[v], v))
	return d

def GP(it):
	return [(ch, len(list(g))) for (ch, g) in groupby(it)]

class DLN:

	def __init__(self, val):
		self.val = val
		self.pre = None
		self.next = None

def main():

	def dfs(r, p):
		if len(g[r]) == 1 and p != 0:
			arr.append((n - 1, r))
			return 1
		res = 1
		cur = 0
		for child in g[r]:
			if child != p:
				tmp = dfs(child, r)
				res += tmp
				cur = max(cur, tmp)
		cur = max(cur, n - res)
		arr.append((cur, r))
		return res
	t = N()
	for i in range(t):
		n = N()
		g = [[] for i in range(n + 1)]
		for i in range(n - 1):
			(x, y) = RL()
			g[x].append(y)
			g[y].append(x)
		arr = []
		if n & 1:
			ans = [1, g[1][0]]
			print(*ans)
			print(*ans)
			continue
		dfs(1, 0)
		arr.sort()
		if arr[0][0] != arr[1][0]:
			ans = [1, g[1][0]]
			print(*ans)
			print(*ans)
			continue
		a = arr[0][1]
		b = arr[1][1]
		for child in g[b]:
			if child != a:
				break
		print(b, child)
		print(a, child)
sys.setrecursionlimit(200000)
import threading
threading.stack_size(10 ** 8)
t = threading.Thread(target=main)
t.start()
t.join()


from __future__ import division, print_function
from fractions import Fraction
import sys
import os
from io import BytesIO, IOBase
from itertools import *
import bisect
from heapq import *
from math import *
from copy import *
from collections import deque
from collections import Counter as counter
from itertools import combinations as comb
from itertools import permutations as permutate
from bisect import bisect_left as bl
from bisect import bisect_right as br
from bisect import bisect
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
from types import GeneratorType

def iterative(f, stack=[]):

	def wrapped_func(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		to = f(*args, **kwargs)
		while True:
			if type(to) is GeneratorType:
				stack.append(to)
				to = next(to)
				continue
			stack.pop()
			if not stack:
				break
			to = stack[-1].send(to)
		return to
	return wrapped_func
mod = 1000000007

def inp():
	return sys.stdin.readline().rstrip('\r\n')

def out(var):
	sys.stdout.write(str(var))

def lis():
	return list(map(int, inp().split()))

def stringlis():
	return list(map(str, inp().split()))

def sep():
	return map(int, inp().split())

def strsep():
	return map(str, inp().split())

def zerolist(n):
	return [0] * n

def nextline():
	out('\n')

def testcase(t):
	for pp in range(t):
		solve(pp)

def printlist(a):
	for p in range(0, len(a)):
		out(str(a[p]) + ' ')

def google(p):
	print('Case #' + str(p) + ': ', end='')

def lcm(a, b):
	return a * b // gcd(a, b)

def power(x, y, p):
	res = 1
	x = x % p
	if x == 0:
		return 0
	while y > 0:
		if y & 1 == 1:
			res = res * x % p
		y = y >> 1
		x = x * x % p
	return res

def ncr(n, r):
	return factorial(n) // (factorial(r) * factorial(max(n - r, 1)))

def isPrime(n):
	if n <= 1:
		return False
	if n <= 3:
		return True
	if n % 2 == 0 or n % 3 == 0:
		return False
	i = 5
	while i * i <= n:
		if n % i == 0 or n % (i + 2) == 0:
			return False
		i = i + 6
	return True

@iterative
def dfs(v, visited, st, sub, par):
	visited[st] = 1
	for i in v[st]:
		if visited[i] == 0:
			ok = (yield dfs(v, visited, i, sub, par))
			sub[st] += sub[i]
			par[i] = st
	yield True

@iterative
def dfslol(v, visited, st, a, edeg):
	visited[st] = 1
	for i in v[st]:
		if visited[i] == 0 and i != a:
			ok = (yield dfslol(v, visited, i, a, edeg))
			if len(v[i]) == 1 and len(edeg) == 0:
				edeg.append(st)
				edeg.append(i)
	yield True

def solve(case):
	n = int(inp())
	g = [[] for i in range(n)]
	help = []
	for i in range(n - 1):
		(x, y) = sep()
		x -= 1
		y -= 1
		if len(help) == 0:
			help.append(x)
			help.append(y)
		g[x].append(y)
		g[y].append(x)
	sub = [1] * n
	vis = [0] * n
	par = [-1] * n
	dfs(g, vis, 0, sub, par)
	if n % 2 == 1:
		print(help[0] + 1, help[1] + 1)
		print(help[0] + 1, help[1] + 1)
		return
	centroids = []
	maxmin = 10 ** 10
	for i in range(n):
		curr = 0
		for j in g[i]:
			if j == par[i]:
				curr = max(curr, n - sub[i])
			else:
				curr = max(curr, sub[j])
		maxmin = min(maxmin, curr)
	for i in range(n):
		curr = 0
		for j in g[i]:
			if j == par[i]:
				curr = max(curr, n - sub[i])
			else:
				curr = max(curr, sub[j])
		if curr == maxmin:
			centroids.append(i)
	if len(centroids) == 1:
		print(help[0] + 1, help[1] + 1)
		print(help[0] + 1, help[1] + 1)
		return
	vis = [0] * n
	edge = []
	dfslol(g, vis, centroids[1], centroids[0], edge)
	print(edge[0] + 1, edge[1] + 1)
	print(centroids[0] + 1, edge[1] + 1)
testcase(int(inp()))


import io, os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
from collections import deque

def answer(n, t):
	sub = [0] * (n + 1)
	centroid = []
	order = []
	parent = [0] * (n + 1)
	q = deque([(1, 0)])
	while q:
		(v, p) = q.popleft()
		order.append(v)
		parent[v] = p
		for i in t[v]:
			if i != p:
				q.append((i, v))
	for i in range(n - 1, -1, -1):
		isc = True
		for j in t[order[i]]:
			if order[i] == parent[j]:
				sub[order[i]] += 1 + sub[j]
				if 1 + sub[j] > n // 2:
					isc = False
		if n - (sub[order[i]] + 1) > n // 2:
			isc = False
		if isc:
			centroid.append(order[i])
	if len(centroid) == 1:
		return ([1, t[1][0]], [1, t[1][0]])
	else:
		node = centroid[1]
		k = 0
		for i in t[node]:
			if i != centroid[0]:
				k = i
				break
		return ([node, k], [centroid[0], k])
t = int(input())
for i in range(t):
	n = int(input())
	t = [[] for i in range(n + 1)]
	for i in range(n - 1):
		(x, y) = map(int, input().split())
		t[x].append(y)
		t[y].append(x)
	(a, b) = answer(n, t)
	print(*a)
	print(*b)


import sys
input = sys.stdin.buffer.readline

class UnionFind:

	def __init__(self, n):
		self.parent = [-1] * n
		self.n = n
		self.cnt = n

	def root(self, x):
		if self.parent[x] < 0:
			return x
		else:
			self.parent[x] = self.root(self.parent[x])
			return self.parent[x]

	def merge(self, x, y):
		x = self.root(x)
		y = self.root(y)
		if x == y:
			return False
		if self.parent[x] > self.parent[y]:
			(x, y) = (y, x)
		self.parent[x] += self.parent[y]
		self.parent[y] = x
		self.cnt -= 1
		return True

	def is_same(self, x, y):
		return self.root(x) == self.root(y)

	def size(self, x):
		return -self.parent[self.root(x)]

	def count(self):
		return self.cnt

	def groups(self):
		res = [[] for _ in range(self.n)]
		for i in range(self.n):
			res[self.root(i)].append(i)
		return [group for group in res if group]

def topological_sorted(tree: list, root: int) -> list:
	n = len(tree)
	visited = [False] * n
	visited[root] = True
	tp_order = [root]
	stack = [root]
	while stack:
		v = stack.pop()
		for nxt_v in tree[v]:
			if visited[nxt_v]:
				continue
			visited[nxt_v] = True
			stack.append(nxt_v)
			tp_order.append(nxt_v)
	return tp_order
t = int(input())
for _ in range(t):
	n = int(input())
	info = [list(map(int, input().split())) for i in range(n - 1)]
	tree = [[] for i in range(n)]
	for (u, v) in info:
		u -= 1
		v -= 1
		tree[u].append(v)
		tree[v].append(u)
	root = 0
	tp_order = topological_sorted(tree, root)
	cnt = [-1] * n
	cent = [0] * n
	for v in tp_order[::-1]:
		max_ = 0
		c = 0
		for nxt_v in tree[v]:
			if cnt[nxt_v] == -1:
				continue
			else:
				c += cnt[nxt_v]
				max_ = max(cnt[nxt_v], max_)
		nokori = n - (c + 1)
		cent[v] = max(nokori, max_)
		cnt[v] = c + 1
	min_cent = min(cent)
	cands = []
	for v in range(n):
		if cent[v] == min_cent:
			cands.append(v)
	if len(cands) == 1:
		print(*info[0])
		print(*info[0])
	else:
		(v1, v2) = (cands[0], cands[1])
		for u1 in tree[v1]:
			if u1 == v2:
				continue
			else:
				break
		print(v1 + 1, u1 + 1)
		print(v2 + 1, u1 + 1)


import threading, sys
threading.stack_size(2 ** 26)
sys.setrecursionlimit(10 ** 6)

def main():
	t = int(input())
	for ii in range(t):
		n = int(input())
		tree = []
		for i in range(n):
			tree.append([])
		for i in range(n - 1):
			(x, y) = map(int, input().split())
			x -= 1
			y -= 1
			tree[x].append(y)
			tree[y].append(x)
		visited = [-1] * n
		nodelabel = [-1] * n

		def dfs(node, parent):
			visited[node] = 1
			for i in tree[node]:
				if visited[i] == -1:
					dfs(i, node)
			if len(tree[node]) == 1:
				nodelabel[node] = 0
			else:
				minimum = 0
				for j in tree[node]:
					if j != parent:
						minimum += nodelabel[j] + 1
				nodelabel[node] = minimum
		dfs(0, None)
		cuts = [-1] * n
		for i in range(n):
			m = -1
			for j in tree[i]:
				if nodelabel[j] > nodelabel[i]:
					m = max(m, n - 1 - nodelabel[i])
				else:
					m = max(m, nodelabel[j] + 1)
			cuts[i] = m
		c = sorted(cuts)
		if c[0] != c[1]:
			print(1, tree[0][0] + 1)
			print(1, tree[0][0] + 1)
		else:
			idx = []
			for i in range(n):
				if cuts[i] == c[0]:
					idx.append(i)
			root = idx[0]
			visited = [-1] * n
			ans = []

			def dfs2(node):
				visited[node] = 1
				for i in tree[node]:
					if visited[i] == -1 and i != idx[1]:
						dfs2(i)
				if len(tree[node]) == 1:
					ans.append((node, tree[node][0]))
			dfs2(root)
			print(ans[0][0] + 1, ans[0][1] + 1)
			print(idx[1] + 1, ans[0][0] + 1)
threading.Thread(target=main).start()


import sys
input = sys.stdin.readline
import sys
import heapq
import copy
import math
import decimal

def inp():
	return int(input())

def inlt():
	return list(map(int, input().split()))

def insr():
	s = input()
	return list(s[:len(s) - 1])

def insr2():
	s = input()
	s = list(s[:len(s) - 1])
	s = [ord(s[i]) - ord('a') for i in range(len(s))]
	return s

def invr():
	return map(int, input().split())
ans = 0

def pr_list(a):
	print(*a, sep=' ')

def swap(a, b):
	temp = a
	a = b
	b = temp
	return [a, b]

def pri(a, b):
	s = '? ' + str(a) + ' ' + str(b)
	print(s)
	sys.stdout.flush()

def main():
	tests = inp()
	mod = 1000000007
	limit = 10 ** 18
	ans = 0
	stack = []
	hashm = {}
	arr = []
	heapq.heapify(arr)

	def find_next(hashm, itr):
		for i in range(itr, len(hashm)):
			if hashm[i] == 0:
				return i
	for test in range(tests):
		n = inp()
		edges = [{} for i in range(n + 1)]
		dum = []
		for j in range(n - 1):
			[a, b] = inlt()
			edges[a][b] = 1
			edges[b][a] = 1
			dum = [a, b]
		children = [0 for i in range(n + 1)]
		done = [-1 for i in range(n + 1)]
		stack = [1]
		done[1] = 1
		while stack != []:
			curr = stack[-1]
			flag = 0
			for child in edges[curr]:
				if done[child] == -1:
					done[child] = 1
					flag = 1
					stack.append(child)
				if curr in edges[child]:
					del edges[child][curr]
			if flag == 1:
				continue
			curr = stack.pop()
			c = 0
			for i in edges[curr]:
				c = c + children[i] + 1
			children[curr] = c
		centroid = [[sys.maxsize, i] for i in range(n + 1)]
		for i in range(1, n + 1):
			sums = 0
			maxi = -1 * sys.maxsize
			for j in edges[i]:
				sums = sums + children[j] + 1
				maxi = max(maxi, children[j] + 1)
			maxi = max(maxi, n - 1 - sums)
			centroid[i][0] = maxi
		centroid.sort()
		if centroid[0][0] != centroid[1][0]:
			pr_list(dum)
			pr_list(dum)
			continue
		a = centroid[0][1]
		b = centroid[1][1]

		def find_leaf(a, b):
			done = [0 for i in range(n + 1)]
			done[a] = 1
			stack = [a]
			leaf = []
			while stack != [] and leaf == []:
				curr = stack.pop()
				for i in edges[curr]:
					if len(edges[i]) == 0:
						leaf = [curr, i]
						return leaf
					elif i != b and done[i] != 1:
						done[i] = 1
						stack.append(i)
			return leaf
		leaf = find_leaf(a, b)
		if leaf == []:
			leaf = find_leaf(b, a)
			pr_list(leaf)
			n_edge = [leaf[1], a]
			pr_list(n_edge)
		else:
			pr_list(leaf)
			n_edge = [leaf[1], b]
			pr_list(n_edge)
main()


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from collections import deque, defaultdict
t = int(input())
for j in range(t):
	n = int(input())
	graph = [[] for s in range(n)]
	for s in range(n - 1):
		(x, y) = map(int, input().split())
		x -= 1
		y -= 1
		graph[x].append(y)
		graph[y].append(x)
	root = 0
	for s in range(n):
		if len(graph[s]) > 0:
			root = s
			break
	depth = defaultdict(list)
	dd = {}
	q = deque([root])
	v1 = set([root])
	cv = 0
	pr = 1
	while len(q) > 0:
		v0 = q.popleft()
		for s in graph[v0]:
			if not s in v1:
				q.append(s)
				v1.add(s)
		depth[cv].append(v0)
		dd[v0] = cv
		pr -= 1
		if pr == 0:
			cv += 1
			pr = len(q)
	cv -= 1
	dist = defaultdict(int)
	while cv > 0:
		for s in depth[cv]:
			for b in graph[s]:
				if cv > dd[b]:
					dist[b] += dist[s] + 1
		cv -= 1
	cand = []
	mincen = n + 1
	for s in range(n):
		if len(graph[s]) > 0:
			cen = 0
			for i in graph[s]:
				if dd[i] > dd[s]:
					cen = max(cen, dist[i] + 1)
				else:
					cen = max(cen, n - (dist[s] + 1))
			if cen < mincen:
				cand = [s]
				mincen = cen
			elif cen == mincen:
				cand.append(s)
	if len(cand) == 1:
		print(cand[0] + 1, graph[cand[0]][0] + 1)
		print(cand[0] + 1, graph[cand[0]][0] + 1)
	else:
		leaf = set([])
		canset = set(cand)
		for s in range(n):
			if len(graph[s]) == 1:
				leaf.add(s)
		queue = deque([cand[0]])
		visited = set([])
		while len(queue) > 0:
			v0 = queue.popleft()
			for s in graph[v0]:
				if not s in canset and (not s in visited):
					queue.append(s)
					visited.add(s)
					if s in leaf:
						leaf.remove(s)
		rand = leaf.pop()
		other = graph[rand][0]
		print(rand + 1, other + 1)
		print(cand[0] + 1, rand + 1)


import os
import sys
from io import BytesIO, IOBase
from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

def DFS(adj):
	parent = {}
	N = len(adj)
	dp = [1] * N
	centroid = [-1] * N

	@bootstrap
	def DFS_use(adj, s):
		sm = 0
		mx = 0
		for i in adj[s]:
			if i not in parent:
				parent[i] = s
				val_sub = (yield DFS_use(adj, i))
				sm += val_sub
				mx = max(mx, val_sub)
		dp[s] += sm
		centroid[s] = max(mx, N - dp[s])
		yield dp[s]
	s = 0
	parent[s] = None
	DFS_use(adj, s)
	return centroid

def find_centroid(adj):
	pass

def main():
	T = iin()
	while T:
		T -= 1
		n = iin()
		adj = [[] for i in range(n)]
		for _ in range(n - 1):
			(i, j) = lin()
			adj[i - 1].append(j - 1)
			adj[j - 1].append(i - 1)
		c1 = DFS(adj)
		c1 = [[c1[i], i] for i in range(n)]
		c1.sort()
		mn = c1[0][0]
		c2 = []
		for (val, idx) in c1:
			if val == mn:
				c2.append(idx)
		ch1 = c2[0]
		sol = [[adj[ch1][0], ch1], [adj[ch1][0], ch1]]
		if len(c2) > 1:
			(ch1, ch2) = (c2[0], c2[1])
			for v in adj[ch1]:
				if v != ch2:
					sol = [[v, ch1], [v, ch2]]
					break
		for (i, j) in sol:
			print(i + 1, j + 1)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def iin():
	return int(input())

def lin():
	return list(map(int, input().split()))
main()


from sys import stdin, stdout, setrecursionlimit
import heapq
from math import gcd, ceil, sqrt
from collections import Counter, deque
from bisect import bisect_left, bisect_right
ii1 = lambda : int(stdin.readline().strip())
is1 = lambda : stdin.readline().strip()
iia = lambda : list(map(int, stdin.readline().strip().split()))
isa = lambda : stdin.readline().strip().split()
setrecursionlimit(100000)
mod = 1000000007

def bfs(d):
	queue = deque([1])
	order = []
	par = {1: 0}
	seen = set([1])
	while len(queue):
		cur = queue.popleft()
		order.append(cur)
		for neigh in d.get(cur, []):
			if neigh not in seen:
				seen.add(neigh)
				par[neigh] = cur
				queue.append(neigh)
	order = order[::-1]
	childs = [1] * len(d)
	cnt = [0] * len(d)
	for i in order:
		if par[i] != 0:
			childs[par[i] - 1] += childs[i - 1]
	for i in range(len(d)):
		if childs[i] * 2 == len(d):
			for j in d[i + 1]:
				if j != par[i + 1]:
					cur = j
			print(i + 1, cur)
			print(par[i + 1], cur)
			break
	else:
		print(1, d[1][0])
		print(1, d[1][0])
tc = ii1()
for _ in range(tc):
	n = ii1()
	d = {}
	for i in range(n - 1):
		(a, b) = iia()
		d.setdefault(a, []).append(b)
		d.setdefault(b, []).append(a)
	bfs(d)


import sys
from array import array
import typing as Tp

def input():
	return sys.stdin.buffer.readline().decode('utf-8')

def output(*args):
	sys.stdout.buffer.write(('\n'.join(map(str, args)) + '\n').encode('utf-8'))

def main():
	from functools import reduce
	from operator import mul
	t = int(input())
	ans_a = [''] * t
	for ti in range(t):
		n = int(input())
		adj = [[] for _ in range(n + 1)]
		deg = [0, 1] + [0] * n
		for (u, v) in (map(int, input().split()) for _ in range(n - 1)):
			adj[u].append(v)
			adj[v].append(u)
			deg[u] += 1
			deg[v] += 1
		subsize = [0] * (n + 1)
		centroid = []
		stack = [i for i in range(2, n + 1) if deg[i] == 1]
		while stack:
			v = stack.pop()
			deg[v] = 0
			subsize[v] = 1
			for dest in adj[v]:
				if subsize[dest]:
					subsize[v] += subsize[dest]
				else:
					deg[dest] -= 1
					if deg[dest] == 1:
						stack.append(dest)
			if all((subsize[dest] * 2 <= n for dest in adj[v] if subsize[dest])) and (n - subsize[v]) * 2 <= n:
				centroid.append(v)
		if len(centroid) == 1:
			ans_a[ti] = f'1 {adj[1][0]}\n1 {adj[1][0]}'
		elif len(centroid) == 2:
			x = [v for v in adj[centroid[0]] if v != centroid[1]][0]
			ans_a[ti] = f'{centroid[0]} {x}\n{centroid[1]} {x}'
		else:
			raise Exception('aaa', centroid)
	output(*ans_a)
main()


import sys
import math, bisect
sys.setrecursionlimit(10 ** 5)
from collections import defaultdict
from itertools import groupby, accumulate
from heapq import heapify, heappop, heappush
from collections import deque, Counter, OrderedDict

def I():
	return int(sys.stdin.readline())

def neo():
	return map(int, sys.stdin.readline().split())

def Neo():
	return list(map(int, sys.stdin.readline().split()))
for _ in range(int(input())):
	n = int(input())
	g = defaultdict(list)
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		g[u].append(v)
		g[v].append(u)
	d = [1] * (n + 1)
	p = [0] * (n + 1)
	l = [10 ** 6] * (n + 1)
	q = deque([1])
	v = [0] * (n + 1)
	v[1] = 1
	rec = []
	c = defaultdict(list)
	while q:
		x = q.popleft()
		rec.append(x)
		for i in g[x]:
			if v[i] == 0:
				v[i] = 1
				p[i] = x
				c[x].append(i)
				q.append(i)
	rec.reverse()
	for i in rec:
		for j in c[i]:
			d[i] += d[j]
	x = max(d)
	for i in range(1, n + 1):
		mm = -1
		for j in c[i]:
			mm = max(mm, d[j])
		mm = max(mm, x - d[i])
		l[i] = mm
	m = min(l)
	cnt = l.count(m)
	if cnt == 1:
		print(1, c[1][0])
		print(1, c[1][0])
	else:
		for i in range(1, n + 1):
			if l[i] == m:
				break
		for j in range(i + 1, n + 1):
			if l[j] == m:
				break
		m = 10 ** 9
		mi = -1
		for k in g[j]:
			if k == i:
				continue
			if m > d[k]:
				m = d[k]
				mi = k
		print(j, mi)
		print(i, mi)


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	N = int(input())
	e = [[] for _ in range(N + 1)]
	for _ in range(N - 1):
		(u, v) = map(int, input().split())
		e[u].append(v)
		e[v].append(u)
	size = [1] * (N + 1)
	parent = [0] * (N + 1)
	order = []
	vis = [0] * (N + 1)
	s = [1]
	vis[1] = 1
	while len(s):
		x = s.pop()
		order.append(x)
		for y in e[x]:
			if vis[y]:
				continue
			vis[y] = 1
			s.append(y)
			parent[y] = x
	order.reverse()
	for y in order[:-1]:
		x = parent[y]
		size[x] += size[y]
	mn = N + 1
	for x in range(1, N + 1):
		t = 0
		for y in e[x]:
			if parent[y] == x:
				t = max(t, size[y])
			else:
				t = max(t, N - size[x])
		mn = min(mn, t)
	centroids = []
	for x in range(1, N + 1):
		t = 0
		for y in e[x]:
			if parent[y] == x:
				t = max(t, size[y])
			else:
				t = max(t, N - size[x])
		if t == mn:
			centroids.append(x)
	if len(centroids) == 1:
		print(1, e[1][0])
		print(1, e[1][0])
	else:
		l = centroids[0]
		r = centroids[1]
		lmax = 0
		t = 0
		for y in e[l]:
			if y == r:
				continue
			if parent[y] == x:
				if t < size[y]:
					lmax = y
					t = size[y]
			elif t < N - size[x]:
				lmax = y
				t = N - size[x]
		print(*sorted([l, lmax]))
		print(*sorted([r, lmax]))


import sys
input = sys.stdin.readline
from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

@bootstrap
def dfs(v, p, cen):
	s[v] = 1
	g = 1
	for i in d[v]:
		if i != p:
			yield dfs(i, v, cen)
			s[v] = s[v] + s[i]
			if s[i] > n // 2:
				g = 0
	if n - s[v] > n // 2:
		g = 0
	if g == 1:
		cen.append(v)
	yield
for _ in range(int(input())):
	n = int(input())
	d = {}
	s = {}
	for _ in range(n - 1):
		(x, y) = map(int, input().split())
		if x in d:
			o = d[x]
			o.append(y)
			d[x] = o
		else:
			d[x] = [y]
		if y in d:
			o = d[y]
			o.append(x)
			d[y] = o
		else:
			d[y] = [x]
	for i in range(1, n + 1):
		s[i] = 1
	cen = []
	dfs(1, -1, cen)
	if len(cen) == 1:
		o = d[cen[0]]
		e1 = cen[0]
		e2 = o[0]
		print(e1, e2)
		print(e1, e2)
	else:
		for i in d[cen[0]]:
			if i != cen[1]:
				print(cen[0], i)
				print(cen[1], i)
				break


import sys
input = sys.stdin.buffer.readline

def solve(N, graph):
	stack = [0]
	Par = [-1] * N
	checked = [False] * N
	Children = [1] * N
	checked[0] = True
	Ch = [-1] * N
	while stack:
		p = stack.pop()
		if p >= 0:
			stack.append(~p)
			for np in graph[p]:
				if not checked[np]:
					checked[np] = True
					Par[np] = p
					Ch[p] = np
					stack.append(np)
		else:
			p = ~p
			if p > 0:
				Children[Par[p]] += Children[p]
	if N % 2 == 1:
		return (1, graph[0][0] + 1, 1, graph[0][0] + 1)
	for n in range(N):
		if Children[n] == N // 2:
			m = Par[n]
			l = n
			while Ch[l] != -1:
				l = Ch[l]
			return (Par[l] + 1, l + 1, m + 1, l + 1)
	return (1, graph[0][0] + 1, 1, graph[0][0] + 1)
Q = int(input())
for _ in range(Q):
	N = int(input())
	graph = [[] for _ in range(N)]
	for _ in range(N - 1):
		(a, b) = map(int, input().split())
		graph[a - 1].append(b - 1)
		graph[b - 1].append(a - 1)
	(a, b, c, d) = solve(N, graph)
	print(a, b)
	print(c, d)


import sys
import threading
from sys import stdin, stdout
sys.setrecursionlimit(10 ** 9)
threading.stack_size(16 * 2048 * 2048)
res = []
mx = 0

def link_cut_centroids(n, dic):
	global res
	global mx
	res = []
	mx = 2 ** 31 - 1
	dfs(1, -1, dic, n)
	if len(res) == 1:
		x1 = 1
		y1 = dic[1][0]
		x2 = 1
		y2 = dic[1][0]
	else:
		n1 = res[0]
		n2 = res[1]
		for nxt in dic[n2]:
			if nxt != n1:
				x1 = n2
				y1 = nxt
				break
		x2 = n1
		y2 = nxt
	return [[x1, y1], [x2, y2]]

def dfs(node, pnode, dic, n):
	global res
	global mx
	cnt = 1
	mxcnt = 0
	for nxt in dic[node]:
		if nxt != pnode:
			lcnt = dfs(nxt, node, dic, n)
			mxcnt = max(lcnt, mxcnt)
			cnt += lcnt
	mxcnt = max(mxcnt, n - cnt)
	if mxcnt < mx:
		res = [node]
		mx = mxcnt
	elif mxcnt == mx:
		res.append(node)
	return cnt

def solve():
	t = int(stdin.readline())
	for _ in range(t):
		n = int(stdin.readline())
		dic = {}
		for _ in range(n - 1):
			(x, y) = map(int, stdin.readline().split())
			if x not in dic:
				dic[x] = []
			if y not in dic:
				dic[y] = []
			dic[x].append(y)
			dic[y].append(x)
		res = link_cut_centroids(n, dic)
		stdout.write(' '.join(map(str, res[0])) + '\n')
		stdout.write(' '.join(map(str, res[1])) + '\n')
threading.Thread(target=solve).start()


import sys
inp = sys.stdin.buffer.readline
inar = lambda : list(map(int, inp().split()))
inin = lambda : int(inp())
inst = lambda : inp().decode().rstrip('\n\r')
from types import GeneratorType

def recursive(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

def centroid(g):
	n = len(g)
	centroid = []
	size = [0 for i in range(n)]

	@recursive
	def dfs(node, par):
		size[node] = 1
		iscent = True
		for nei in g[node]:
			if nei != par:
				yield dfs(nei, node)
				size[node] += size[nei]
				if size[nei] > n // 2:
					iscent = False
		if n - size[node] > n // 2:
			iscent = False
		if iscent:
			centroid.append(node)
		yield
	dfs(0, -1)
	return (centroid, size)
_T_ = inin()
for _t_ in range(_T_):
	n = inin()
	gr = [[] for i in range(n)]
	vis = [False for i in range(n)]
	for i in range(n - 1):
		(x, y) = inar()
		x -= 1
		y -= 1
		gr[x].append(y)
		gr[y].append(x)
	(cent, size) = centroid(gr)
	if len(cent) == 1:
		print(x + 1, y + 1)
		print(x + 1, y + 1)
	else:
		opponent = -1
		maxsize = -12
		to_remove = -1
		for node in cent:
			for nei in gr[node]:
				if size[nei] > maxsize and nei not in cent:
					maxsize = size[nei]
					opponent = node
					to_remove = nei
		if opponent == cent[0]:
			print(cent[0] + 1, to_remove + 1)
			print(cent[1] + 1, to_remove + 1)
		else:
			print(cent[1] + 1, to_remove + 1)
			print(cent[0] + 1, to_remove + 1)


import sys
from collections import defaultdict, deque
from operator import itemgetter
sys.setrecursionlimit(200000)
_DEBUG = False
if _DEBUG:
	sys.stdin = open('c.in')
else:
	input = sys.stdin.readline

def solve(n: int, edges):
	g = defaultdict(set)
	for (a, b) in edges:
		g[a].add(b)
		g[b].add(a)
	deq = deque([1])
	while deq:
		node = deq.popleft()
		for next in g[node]:
			g[next].remove(node)
			deq.append(next)
	calc_order = []
	stack = [1]
	while stack:
		node = stack.pop()
		for child in g[node]:
			calc_order.append((node, child))
			stack.append(child)
	vertex_count = [0] + [1] * n
	for (parent, child) in calc_order[::-1]:
		vertex_count[parent] += vertex_count[child]
	candidates = []
	for i in range(1, n + 1):
		largest_child_count = max((vertex_count[child] for child in g[i])) if g[i] else 0
		largest_sub_component_size = max(largest_child_count, n - vertex_count[i])
		candidates.append((largest_sub_component_size, len(g[i]), i))
	candidates.sort(key=itemgetter(0, 1))
	if candidates[0][0] < candidates[1][0]:
		return [edges[0], edges[0]]
	child = candidates[0][2]
	parent = candidates[1][2]
	if parent in g[child]:
		(child, parent) = (parent, child)
	first_child_of_child = list(g[child])[0]
	return [[child, first_child_of_child], [parent, first_child_of_child]]
for _ in range(int(input())):
	n = int(input())
	edges = []
	for _ in range(n - 1):
		(a, b) = map(int, input().split())
		edges.append((a, b))
	cuts = solve(n, edges)
	for (a, b) in cuts:
		print(a, b)


from sys import stdin, stdout

def main():
	global tree
	t = int(stdin.readline())
	for _ in range(t):
		n = int(stdin.readline())
		tree = [list() for _ in range(n + 1)]
		tree_size = [1 for _ in range(n + 1)]
		p = [0 for _ in range(n + 1)]
		processed = [False for _ in range(n + 1)]
		mx = [0 for _ in range(n + 1)]
		minn = 1000000
		cent1 = -1
		cent2 = -1
		for _ in range(n - 1):
			(a, b) = list(map(int, stdin.readline().split()))
			tree[a].append(b)
			tree[b].append(a)
		temp_tree = [list(row) for row in tree]
		stack = [1]
		while stack:
			cur = stack[-1]
			if temp_tree[cur]:
				if temp_tree[cur][-1] == p[cur]:
					temp_tree[cur].pop()
					continue
				if processed[temp_tree[cur][-1]]:
					child = temp_tree[cur].pop()
					tree_size[cur] += tree_size[child]
					mx[cur] = max(mx[cur], tree_size[child])
					if not temp_tree[cur] or temp_tree[cur][-1] == p[cur]:
						continue
				child = temp_tree[cur][-1]
				p[child] = cur
				processed[child] = True
				stack.append(child)
			else:
				mx[cur] = max(mx[cur], n - tree_size[cur])
				if mx[cur] < minn:
					minn = mx[cur]
					cent1 = cur
					cent2 = -1
				elif minn == mx[cur]:
					cent2 = cur
				stack.pop()
		if cent2 == -1:
			print(1, tree[1][0], 1, tree[1][0])
			continue
		if p[cent1] != cent2:
			(cent1, cent2) = (cent2, cent1)
		stack = [cent1]
		ans = -1
		while stack:
			cur = stack[-1]
			if len(tree[cur]) == 1:
				ans = cur
				break
			if tree[cur][-1] == p[cur]:
				stack.append(tree[cur][0])
			else:
				stack.append(tree[cur][-1])
		print(ans, tree[ans][0], ans, cent2)
main()


import os
import sys
from io import BytesIO, IOBase
_str = str
BUFSIZE = 8192

def str(x=b''):
	return x if type(x) is bytes else _str(x).encode()

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def inp():
	return sys.stdin.readline().rstrip()

def mpint():
	return map(int, inp().split(' '))

def itg():
	return int(inp())

def tree_bfs(tree, flat=True, start=0) -> list:
	stack = [start]
	result = []
	while stack:
		new_stack = []
		if flat:
			result.extend(stack)
		else:
			result.append(stack)
		for node in stack:
			new_stack.extend(tree[node])
		stack = new_stack
	return result

def tree_postorder(tree, flat=True, root=0):
	return tree_bfs(tree, flat, root)[::-1]

def get_parent_list(tree):
	result = [0] * len(tree)
	for (parent, children) in enumerate(tree):
		for child in children:
			result[child] = parent
	return result

def edge_descendant(tree, edge_time_count=False):
	vertices = len(tree)
	results = [{} for _ in range(vertices)]
	parent_list = get_parent_list(tree)
	for child in tree_postorder(tree):
		parent = parent_list[child]
		if parent != child:
			results[parent][child] = sum(results[child].values()) + 1
	if edge_time_count:
		for parent in results:
			for child in parent:
				num = parent[child]
				parent[child] = num * (vertices - num)
	return results

def node_split_size(tree) -> list:
	vertices = len(tree)
	results = [list(d.values()) for d in edge_descendant(tree)]
	for descendant in results:
		other = vertices - sum(descendant) - 1
		if other:
			descendant.append(other)
	return results

def to_tree(graph, root=0):
	stack = [[root]]
	while stack:
		if not stack[-1]:
			del stack[-1]
			continue
		parent = stack[-1].pop()
		for child in graph[parent]:
			graph[child].discard(parent)
		stack.append(list(graph[parent]))

def tree_centroid(tree) -> list:
	vertices = len(tree)
	half = vertices >> 1
	split_count = node_split_size(tree)
	centroid = []
	for (node, count) in enumerate(split_count):
		if max(count) <= half:
			centroid.append(node)
			if vertices & 1 or len(centroid) == 2:
				break
	return centroid

def peek(iterable):
	for element in iterable:
		return element

def solve():
	n = itg()
	if n & 1:
		for _ in range(n - 2):
			inp()
		ans = inp()
		print(ans)
		print(ans)
		return
	tree = [set() for _ in range(n)]
	for _ in range(n - 1):
		(u, v) = mpint()
		u -= 1
		v -= 1
		tree[u].add(v)
		tree[v].add(u)
	to_tree(tree)
	centroids = tree_centroid(tree)
	if len(centroids) == 1:
		c1 = centroids[0]
		print(c1 + 1, peek(tree[c1]) + 1)
		print(c1 + 1, peek(tree[c1]) + 1)
		return
	(c1, c2) = centroids
	if c2 in tree[c1]:
		(c1, c2) = (c2, c1)
	parent = c1
	leaf = peek(tree[c1])
	while tree[leaf]:
		parent = leaf
		leaf = peek(tree[leaf])
	print(parent + 1, leaf + 1)
	print(c2 + 1, leaf + 1)

def main():
	for _ in range(itg()):
		solve()
DEBUG = 0
URL = ''
if DEBUG == 1:
	import requests
	from ACgenerator.Y_Test_Case_Runner import TestCaseRunner
	runner = TestCaseRunner(main, URL)
	inp = runner.input_stream
	print = runner.output_stream
	runner.checking()
elif DEBUG == 2:
	main()
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
	main()


import sys
from collections import defaultdict, deque
input = sys.stdin.readline
for _ in range(int(input())):
	n = int(input())
	g = defaultdict(list)
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		g[u].append(v)
		g[v].append(u)
	d = [1] * (n + 1)
	p = [0] * (n + 1)
	l = [10 ** 6] * (n + 1)
	q = deque([1])
	v = [0] * (n + 1)
	v[1] = 1
	rec = []
	c = defaultdict(list)
	while q:
		x = q.popleft()
		rec.append(x)
		for i in g[x]:
			if v[i] == 0:
				v[i] = 1
				p[i] = x
				c[x].append(i)
				q.append(i)
	rec.reverse()
	for i in rec:
		for j in c[i]:
			d[i] += d[j]
	x = max(d)
	for i in range(1, n + 1):
		mm = -1
		for j in c[i]:
			mm = max(mm, d[j])
		mm = max(mm, x - d[i])
		l[i] = mm
	m = min(l)
	cnt = l.count(m)
	if cnt == 1:
		print(1, c[1][0])
		print(1, c[1][0])
	else:
		for i in range(1, n + 1):
			if l[i] == m:
				break
		for j in range(i + 1, n + 1):
			if l[j] == m:
				break
		m = 10 ** 9
		mi = -1
		for k in g[j]:
			if k == i:
				continue
			if m > d[k]:
				m = d[k]
				mi = k
		print(j, mi)
		print(i, mi)


import os
import sys
from io import BytesIO, IOBase
_str = str
BUFSIZE = 8192

def str(x=b''):
	return x if type(x) is bytes else _str(x).encode()

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))

def inp():
	return sys.stdin.readline().rstrip('\n')

def mpint():
	return map(int, sys.stdin.readline().split(' '))

def itg():
	return int(sys.stdin.readline())
from copy import deepcopy

def to_tree(graph, root=0):
	graph[:] = map(set, graph)
	stack = [[root]]
	while stack:
		if not stack[-1]:
			del stack[-1]
			continue
		vertex = stack[-1].pop()
		for e in graph[vertex]:
			graph[e].remove(vertex)
		stack.append(list(graph[vertex]))
	graph[:] = map(list, graph)

def to_graph(tree, to_list=False):
	tree[:] = map(set, tree)
	for (node1, node_set) in enumerate(deepcopy(tree)):
		for node2 in node_set:
			tree[node2].add(node1)
	if to_list:
		tree[:] = map(list, tree)

def tree_bfs(tree, start=0, flat=False) -> list:
	stack = [start]
	result = []
	while stack:
		new_stack = []
		if flat:
			result.extend(stack)
		else:
			result.append(stack)
		for node in stack:
			new_stack.extend(tree[node])
		stack = new_stack
	return result

def tree_postorder(tree, root=0, flat=False):
	return tree_bfs(tree, root, flat=flat)[::-1]

def tree_edge_descendant(tree, edge_time_count=False, root=0):
	vertices = len(tree)
	graph = deepcopy(tree)
	to_graph(graph)
	results = [[] for _ in range(vertices)]
	for leaves in tree_postorder(tree)[:-1]:
		for leaf in leaves:
			graph[leaf] = list(graph[leaf])
			graph[graph[leaf][0]].remove(leaf)
		for leaf in leaves:
			children = sum(results[leaf]) + 1
			results[graph[leaf][0]].append(children)
	if edge_time_count:
		for result in results:
			result[:] = map(lambda x: x * (vertices - x), result)
	return results

def tree_split_count(tree):
	vertices = len(tree)
	edge_descendant = tree_edge_descendant(tree)
	for descendant in edge_descendant:
		other = vertices - sum(descendant) - 1
		if other:
			descendant.append(other)
	return edge_descendant

def tree_centroid(tree) -> list:
	vertices = len(tree)
	half = vertices >> 1
	split_count = tree_split_count(tree)
	centroid = []
	for (node, count) in enumerate(split_count):
		if max(count) <= half:
			centroid.append(node)
			if vertices & 1 or len(centroid) == 2:
				break
	return centroid
for __ in range(itg()):
	n = itg()
	graph = [[] for _ in range(n)]
	if n & 1:
		for _ in range(n - 2):
			inp()
		ans = inp()
		print(ans)
		print(ans)
		continue
	for _ in range(n - 1):
		(u, v) = mpint()
		u -= 1
		v -= 1
		graph[u].append(v)
		graph[v].append(u)
	tree = deepcopy(graph)
	to_tree(tree)
	centroids = tree_centroid(tree)
	if len(centroids) == 1:
		c1 = centroids[0]
		print(c1 + 1, graph[c1][0] + 1)
		print(c1 + 1, graph[c1][0] + 1)
		continue
	(c1, c2) = centroids
	if c2 in tree[c1]:
		(c1, c2) = (c2, c1)
	parent = c1
	leaf = tree[c1][0]
	while tree[leaf]:
		parent = leaf
		leaf = tree[leaf][0]
	print(parent + 1, leaf + 1)
	print(c2 + 1, leaf + 1)


import sys
import math
import bisect
from sys import stdin, stdout
from math import gcd, floor, sqrt, log2, ceil
from collections import defaultdict as dd
from bisect import bisect_left as bl, bisect_right as br
from bisect import insort
from collections import Counter
from collections import deque
from heapq import heappush, heappop, heapify
from itertools import permutations, combinations
mod = int(1000000000.0) + 7
ip = lambda : int(stdin.readline())
inp = lambda : map(int, stdin.readline().split())
ips = lambda : stdin.readline().rstrip()
out = lambda x: stdout.write(str(x) + '\n')
import sys
sys.setrecursionlimit(10 ** 9)
import threading
threading.stack_size(67108864)
INF = 10 ** 9
min_size = INF
min_size_vertices = []

def input():
	return sys.stdin.readline().rstrip()

def addEdgeListToAdjList(edgeList, adjList, isDirectedGraph=False):
	for edge in edgeList:
		adjList[edge[0]].append(edge[1])
		if isDirectedGraph == False:
			adjList[edge[1]].append(edge[0])

def dfs(startVertex, adjList, isVisited):
	global min_size
	global min_size_vertices
	isVisited[startVertex] = True
	n = len(adjList) - 1
	totalVerticesInSubTree = 1
	maxi_childSubTreeSize = 0
	for vertex in adjList[startVertex]:
		if isVisited[vertex] == False:
			count = dfs(vertex, adjList, isVisited)
			maxi_childSubTreeSize = max(maxi_childSubTreeSize, count)
			totalVerticesInSubTree += count
	maxi_childSubTreeSize = max(maxi_childSubTreeSize, n - totalVerticesInSubTree)
	if maxi_childSubTreeSize < min_size:
		min_size = maxi_childSubTreeSize
		min_size_vertices = [startVertex]
	elif maxi_childSubTreeSize == min_size:
		min_size_vertices.append(startVertex)
	return totalVerticesInSubTree

def main():
	global min_size
	global min_size_vertices
	t = int(input())
	for i in range(t):
		min_size = INF
		min_size_vertices = []
		n = int(input())
		edgeList = [list(map(int, input().split())) for i in range(0, n - 1)]
		adjList = [[] for i in range(0, n + 1)]
		isVisited = [False for i in range(0, n + 1)]
		addEdgeListToAdjList(edgeList, adjList)
		dfs(1, adjList, isVisited)
		if len(min_size_vertices) < 2:
			print(' '.join(map(str, edgeList[0])))
			print(' '.join(map(str, edgeList[0])))
		else:
			val1 = min_size_vertices[0]
			val2 = min_size_vertices[1]
			val3 = adjList[val1][0]
			if val3 == val2:
				val3 = adjList[val1][1]
			print(str(val3) + ' ' + str(val1))
			print(str(val3) + ' ' + str(val2))
thread = threading.Thread(target=main)
thread.start()
thread.join()


import sys
sys.setrecursionlimit(10 ** 5)
int1 = lambda x: int(x) - 1
p2D = lambda x: print(*x, sep='\n')

def II():
	return int(sys.stdin.readline())

def MI():
	return map(int, sys.stdin.readline().split())

def MI1():
	return map(int1, sys.stdin.readline().split())

def LI():
	return list(map(int, sys.stdin.readline().split()))

def LLI(rows_number):
	return [LI() for _ in range(rows_number)]

def SI():
	return sys.stdin.readline()[:-1]
for _ in range(II()):
	n = II()
	to = [[] for _ in range(n)]
	for _ in range(n - 1):
		(u, v) = MI1()
		to[u].append(v)
		to[v].append(u)
	if n % 2:
		print(1, to[0][0] + 1)
		print(1, to[0][0] + 1)
		continue
	size = [-1] * n
	stack = [(0, -1)]
	pp = [-1] * n
	while stack:
		(u, pu) = stack.pop()
		if size[u] == -1:
			size[u] = 1
			stack.append((u, pu))
			for v in to[u]:
				if v == pu:
					continue
				pp[v] = u
				stack.append((v, u))
		elif pu != -1:
			size[pu] += size[u]
	for u in range(n):
		if size[u] == n // 2:
			for w in to[u]:
				if w != pp[u]:
					print(u + 1, w + 1)
					print(pp[u] + 1, w + 1)
					break
			break
	else:
		print(1, to[0][0] + 1)
		print(1, to[0][0] + 1)


import sys
import threading
sys.setrecursionlimit(10 ** 6)
threading.stack_size(10 ** 8)

def main():
	t = int(input())
	for _ in range(t):
		n = int(input())
		adj = [[] for _ in range(n)]
		for _ in range(n - 1):
			(u, v) = [int(x) - 1 for x in input().split()]
			adj[u].append(v)
			adj[v].append(u)
		max_size = [0] * n
		compute_sizes(0, -1, max_size, adj)
		min_max_size = min(max_size)
		centroids = [i for (i, s) in enumerate(max_size) if s == min_max_size]
		if len(centroids) == 1:
			print(f'1 {adj[0][0] + 1}')
			print(f'1 {adj[0][0] + 1}')
		else:
			(c1, c2) = centroids
			u = adj[c1][0]
			if u == c2:
				u = adj[c1][1]
			print(f'{c1 + 1} {u + 1}')
			print(f'{c2 + 1} {u + 1}')

def compute_sizes(u, p, max_size, adj):
	size = 1
	for v in adj[u]:
		if v != p:
			subtree_size = compute_sizes(v, u, max_size, adj)
			max_size[u] = max(max_size[u], subtree_size)
			size += subtree_size
	max_size[u] = max(max_size[u], len(adj) - size)
	return size
threading.Thread(target=main).start()


from sys import setrecursionlimit
setrecursionlimit(10 ** 8)
import threading
threading.stack_size(10 ** 8)

def best(p, prev):
	x = 0
	for i in child[p]:
		if i != prev:
			x += best(i, p) + 1
			dp[p] += dp[i]
	dp[p] += x
	nodes[p] = x
	return x

def dfs1(p, prev, lvl):
	level[p] = lvl
	parent[p] = prev
	for i in child[p]:
		if i != prev:
			dp[i] += dp[p] - (dp[i] + nodes[i] + 1) + (n - (nodes[i] + 1))
			dfs1(i, p, lvl + 1)

def dfs(p, prev):
	global leaf
	for i in child[p]:
		if i != prev:
			dfs(i, p)
			break
	if len(child[p]) == 1:
		leaf = p
		print(prev, leaf)
n = 0
(child, dp, nodes, parent, level) = ([], [], [], [], [])
leaf = -1

def main():
	global n
	global child
	global dp, nodes, parent, level
	global leaf
	for T in range(int(input())):
		n = int(input())
		child = [[] for i in range(n + 1)]
		for i in range(n - 1):
			(u, v) = map(int, input().split())
			child[u].append(v)
			child[v].append(u)
		dp = [0] * (n + 1)
		nodes = [0] * (n + 1)
		level = [0] * (n + 1)
		parent = [-1] * (n + 1)
		best(1, -1)
		dfs1(1, -1, 0)
		m = min(dp[1:])
		(x, y) = (-1, -1)
		for i in range(1, n + 1):
			if m == dp[i]:
				if x == -1:
					x = i
				else:
					y = i
		leaf = -1
		if y == -1:
			dfs(x, parent[x])
			print(parent[leaf], leaf)
		elif level[x] < level[y]:
			dfs(y, parent[y])
			print(x, leaf)
		else:
			dfs(x, parent[x])
			print(y, leaf)
threading.Thread(target=main).start()


import sys
input = sys.stdin.buffer.readline
T = int(input())
for testcase in range(T):
	n = int(input())
	edge = [[] for _ in range(n)]
	for _ in range(n - 1):
		(x, y) = map(int, input().split())
		edge[x - 1].append(y - 1)
		edge[y - 1].append(x - 1)
	par = [-1] * n
	order = []
	tank = [0]
	while tank:
		q = tank.pop()
		order.append(q)
		par_q = par[q]
		for e in edge[q]:
			if e != par_q:
				par[e] = q
				tank.append(e)
	size = [1] * n
	flag = [True] * n
	for e in order[::-1]:
		if n - size[e] > n // 2:
			flag[e] = False
		if e == 0:
			break
		if size[e] > n // 2:
			flag[par[e]] = False
		size[par[e]] += size[e]
	c = []
	for i in range(n):
		if flag[i]:
			c.append(i)
	if len(c) == 1:
		print(1, edge[0][0] + 1)
		print(1, edge[0][0] + 1)
	else:
		cen = c[0]
		rem = c[1]
		for e in edge[cen]:
			if e != rem:
				go = e
				break
		print(cen + 1, go + 1)
		print(rem + 1, go + 1)


from collections import deque
import sys
input = sys.stdin.buffer.readline

def prog():
	for _ in range(int(input())):
		n = int(input())
		parent = [0] * (n + 1)
		visited = [0] * (n + 1)
		sz = [0] * (n + 1)
		adj = [[] for i in range(n + 1)]
		for i in range(n - 1):
			(x, y) = map(int, input().split())
			adj[x].append(y)
			adj[y].append(x)
		s = deque([1])
		while s:
			curr = s[-1]
			if not visited[curr]:
				visited[curr] = 1
				for neighbor in adj[curr]:
					if not visited[neighbor]:
						parent[neighbor] = curr
						s.append(neighbor)
			else:
				for neighbor in adj[curr]:
					sz[curr] += sz[neighbor]
				sz[curr] += 1
				s.pop()
		largest = [[0] * 2 for i in range(n + 1)]
		for i in range(1, n + 1):
			curr = 0
			tot = 0
			worst = 0
			for neighbor in adj[i]:
				if neighbor != parent[i]:
					if sz[neighbor] > curr:
						curr = sz[neighbor]
						largest[i][1] = neighbor
					tot += sz[neighbor]
			if n - 1 - tot > curr:
				curr = n - 1 - tot
				largest[i][1] = parent[i]
			largest[i][0] = curr
		least = 10 ** 6
		for i in range(1, n + 1):
			least = min(least, largest[i][0])
		centroids = []
		for i in range(1, n + 1):
			if least == largest[i][0]:
				centroids.append(i)
		if len(centroids) == 1:
			for i in range(2):
				print(f'{centroids[0]} {adj[centroids[0]][0]}')
			continue
		other = centroids[1]
		to_place = largest[centroids[1]][1]
		if to_place == centroids[0]:
			for i in adj[centroids[1]]:
				if i != to_place:
					start = i
					break
		else:
			start = centroids[0]
		s = deque([start])
		visited = [0] * (n + 1)
		while s:
			curr = s[-1]
			if not visited[curr]:
				visited[curr] = 1
				if len(adj[curr]) == 1:
					to_remove = [curr, adj[curr][0]]
					break
				for neighbor in adj[curr]:
					if not visited[neighbor] and neighbor != other:
						s.append(neighbor)
			else:
				s.pop()
		print(*to_remove)
		print(f'{to_remove[0]} {to_place}')
prog()


from sys import stdin, stdout
from math import gcd, sqrt, inf
from collections import deque
input = stdin.readline
R = lambda : map(int, input().split())
I = lambda : int(input())
S = lambda : input().rstrip('\n')
L = lambda : list(R())
hg = lambda x, y: (y + x - 1) // x * x
pw = lambda x: 1 if x == 1 else 1 + pw(x // 2)
chk = lambda x: chk(x // 2) if not x % 2 else True if x == 1 else False
M = inf
for _ in range(I()):
	n = I()
	a = [[] for i in range(n)]
	for i in range(n - 1):
		(x, y) = R()
		x -= 1
		y -= 1
		a[x] += (y,)
		a[y] += (x,)
	stk = [0]
	vst = [1] * n
	val = [0] * n
	sub = [[] for i in range(n)]
	sr = []
	p = [0] * n
	vst[0] = 0
	while stk:
		i = stk.pop()
		for el in a[i]:
			if vst[el]:
				sr += (el,)
				stk += (el,)
				vst[el] = 0
				p[el] = i
	for i in sr[::-1]:
		val[p[i]] += val[i] + 1
		sub[p[i]] += (val[i] + 1,)
		sub[i] += (n - 1 - val[i],)
	sub[0] += (n - 1 - val[0],)
	centroid = []
	for i in range(n):
		if max(sub[i]) <= n // 2:
			centroid += (i,)
	if len(centroid) == 1:
		h = (centroid[0] + 1, a[centroid[0]][0] + 1)
		print(*h)
		print(*h)
	else:
		for i in a[centroid[1]]:
			if i != centroid[0]:
				h = i
				break
		print(centroid[1] + 1, h + 1)
		print(centroid[0] + 1, h + 1)


from sys import stdin, stdout
(readline, printline) = (stdin.readline, stdout.write)

def mint():
	return int(readline())

def mints():
	return list(map(int, readline().split()))

class Node:

	def __init__(self, val):
		self.val = val
		self.neighbours = []
		(self.subtree, self.maxsub) = (1, 0)
		(self.visited, self.parent) = (False, 0)

def dfs(tree):
	q = [-1, 1]
	tree[1].visited = True
	while q:
		v = q.pop()
		if v < 0:
			v = -v
			p = tree[v].parent
			tree[p].subtree += tree[v].subtree
			tree[p].maxsub = max(tree[p].maxsub, tree[v].subtree)
			tree[v].maxsub = max(tree[v].maxsub, n - tree[v].subtree)
		for neighbour in tree[v].neighbours:
			if tree[neighbour].visited:
				continue
			tree[neighbour].parent = v
			q.append(-neighbour)
			q.append(neighbour)
			tree[neighbour].visited = True
	return 1
for _ in range(mint()):
	n = mint()
	graph = {}
	for _ in range(n - 1):
		(x, y) = mints()
		if x not in graph:
			graph[x] = Node(x)
		graph[x].neighbours.append(y)
		if y not in graph:
			graph[y] = Node(y)
		graph[y].neighbours.append(x)
	graph[0] = Node(0)
	graph[0].neighbours.append(1)
	dfs(graph)
	mmcc = graph[min(graph, key=lambda x: graph[x].maxsub)].maxsub
	centroids = [graph[x] for x in range(1, n + 1) if graph[x].maxsub == mmcc]
	i = 0
	if centroids[0].neighbours[i] == centroids[-1].val:
		i += 1
	printline('{} {}\n'.format(centroids[0].val, centroids[0].neighbours[i]))
	printline('{} {}\n'.format(centroids[-1].val, centroids[0].neighbours[i]))


import io
import os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc
from collections import defaultdict, deque
for _ in range(int(input())):
	n = int(input())
	tree = defaultdict(list)
	edges = []
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		tree[u].append(v)
		tree[v].append(u)
		edges.append((u, v))
	level = {}
	stack = deque([1])
	seen = {}
	while stack:
		current = stack[0]
		if len(tree[current]) == 1 and current != 1:
			level[current] = 1
			stack.popleft()
		elif current in seen:
			for child in tree[current]:
				if child in level:
					level[current] = level.get(current, 1) + level[child]
			stack.popleft()
		else:
			for nxt in tree[current]:
				if nxt not in seen:
					stack.appendleft(nxt)
		seen[current] = 1
	mc = [0] * (n + 1)
	for edge in edges:
		(u, v) = (edge[0], edge[1])
		if level[v] < level[u]:
			(u, v) = (v, u)
		mc[u] = max(mc[u], n - level[u])
		mc[v] = max(mc[v], level[u])
	m = n - 1
	for i in range(1, n + 1):
		if mc[i] < m:
			m = mc[i]
	mins = []
	t = 0
	for i in range(1, n + 1):
		if mc[i] == m:
			t += 1
			mins.append(i)
	if t == 1:
		edge = edges[0]
		print(edge[0], edge[1])
		print(edge[0], edge[1])
	else:
		a = mins[0]
		b = mins[1]
		for i in tree[a]:
			if i != b:
				x = i
				break
		print(a, x)
		print(b, x)


from collections import deque
import sys
input = sys.stdin.readline
T = int(input())
from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

def find_centroids(edges):
	N = len(edges)
	centroids = []
	subtree_size = [0] * N

	@bootstrap
	def dfs(u, prev):
		subtree_size[u] = 1
		is_centroid = True
		for v in edges[u]:
			if v != prev:
				yield dfs(v, u)
				subtree_size[u] += subtree_size[v]
				if subtree_size[v] > N // 2:
					is_centroid = False
		if N - subtree_size[u] > N / 2:
			is_centroid = False
		if is_centroid:
			centroids.append(u)
		yield
	dfs(0, -1)
	return centroids

def find_leaf(edges, start_node, blacklist):
	Q = deque()
	Q.append(start_node)
	visited = [False] * len(edges)
	while Q:
		node = Q.popleft()
		visited[node] = True
		found_neighbour = False
		for neighbour in edges[node]:
			if neighbour == blacklist:
				continue
			if visited[neighbour]:
				continue
			Q.append(neighbour)
			found_neighbour = True
		if not found_neighbour:
			return node
for t in range(T):
	N = int(input())
	edges = [set() for _ in range(N)]
	for i in range(N - 1):
		(u, v) = [int(_) for _ in input().split()]
		(anyu, anyv) = (u, v)
		edges[u - 1].add(v - 1)
		edges[v - 1].add(u - 1)
	centroids = find_centroids(edges)
	if len(centroids) <= 1:
		print(anyu, anyv)
		print(anyu, anyv)
	else:
		for neighbour in edges[centroids[0]]:
			if neighbour != centroids[1]:
				leaf1 = find_leaf(edges, neighbour, centroids[0])
				break
		print(leaf1 + 1, next(iter(edges[leaf1])) + 1)
		print(leaf1 + 1, centroids[1] + 1)


from collections import deque, defaultdict
import sys
from types import GeneratorType
input = sys.stdin.readline
MODULO = int(1000000000.0) + 7

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

def compute_adj_list(edges):
	adj_list = defaultdict(list)
	for (src, dst) in edges:
		adj_list[src].append(dst)
		adj_list[dst].append(src)
	return adj_list

@bootstrap
def dfs(current, parent, adj_list, num_childs):
	for child in adj_list[current]:
		if child != parent:
			yield dfs(child, current, adj_list, num_childs)
			num_childs[current] += num_childs[child] + 1
	yield None

def find_centroid(current, parent, adj_list, num_childs, n):
	while True:
		num = 0
		for child in adj_list[current]:
			if child != parent:
				if num_childs[child] + 1 > n // 2:
					(current, parent) = (child, current)
					num += 1
					break
		if num == 0:
			break
	return current

def get_leaf(current, parent, adj_list):
	while True:
		num = 0
		for child in adj_list[current]:
			if child != parent:
				(current, parent) = (child, current)
				num += 1
				break
		if num == 0:
			break
	return (current, parent)

def solution(edges, n):
	adj_list = compute_adj_list(edges)
	num_childs = [0] * n
	root = 0
	dfs(root, -1, adj_list, num_childs)
	centroid = find_centroid(root, -1, adj_list, num_childs, n)
	second_centroid = None
	for child in adj_list[centroid]:
		if num_childs[child] + 1 == n // 2:
			second_centroid = child
	if second_centroid is None:
		child = adj_list[centroid][0]
		print(centroid + 1, child + 1)
		print(centroid + 1, child + 1)
	else:
		(leaf, parent) = get_leaf(second_centroid, centroid, adj_list)
		print(parent + 1, leaf + 1)
		print(centroid + 1, leaf + 1)
k = [int(val) for val in input().split()][0]
for _ in range(k):
	n = [int(val) for val in input().split()][0]
	edges = []
	for _ in range(n - 1):
		(src, dst) = [int(val) - 1 for val in input().split()]
		edges.append([src, dst])
	solution(edges, n)


import sys
import io, os
input = sys.stdin.buffer.readline
t = int(input())
for _ in range(t):
	n = int(input())
	g = [[] for _ in range(n)]
	edges = []
	for i in range(n - 1):
		(x, y) = map(int, input().split())
		(x, y) = (x - 1, y - 1)
		g[x].append(y)
		g[y].append(x)
		edges.append((x, y))
	s = []
	s.append(0)
	parent = [-1] * n
	order = []
	while s:
		v = s.pop()
		order.append(v)
		for u in g[v]:
			if u == parent[v]:
				continue
			parent[u] = v
			s.append(u)
	c = [0] * n
	order.reverse()
	for v in order:
		c[v] += 1
		if parent[v] == -1:
			continue
		c[parent[v]] += c[v]
	ch = [[] for _ in range(n)]
	for v in order:
		if parent[v] == -1:
			continue
		else:
			ch[parent[v]].append(v)
	cent = []
	for v in range(n):
		if n - c[v] > n // 2:
			continue
		for u in ch[v]:
			if c[u] > n // 2:
				break
		else:
			cent.append(v)
	if len(cent) == 1:
		(u, v) = edges[0]
		print(u + 1, v + 1)
		print(u + 1, v + 1)
	else:
		(c1, c2) = (cent[0], cent[1])
		if parent[c1] == c2:
			t = c1
			tt = c2
		else:
			t = c2
			tt = c1
		cnt = n - c[t]
		temp = []
		for u in ch[t]:
			temp.append((c[u], u))
		temp.sort(reverse=True)
		u = temp[0][1]
		print(u + 1, t + 1)
		print(u + 1, tt + 1)


import sys

def inpt():
	return sys.stdin.readline().rstrip()

def read():
	return [int(x) for x in inpt().split()]
from types import GeneratorType

def recursive(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

def centroid(g):
	n = len(g)
	centroid = []
	size = [0 for i in range(n)]

	@recursive
	def dfs(node, par):
		size[node] = 1
		iscent = True
		for nei in g[node]:
			if nei != par:
				yield dfs(nei, node)
				size[node] += size[nei]
				if size[nei] > n // 2:
					iscent = False
		if n - size[node] > n // 2:
			iscent = False
		if iscent:
			centroid.append(node)
		yield
	dfs(0, -1)
	return (centroid, size)
(_T_,) = read()
for _t_ in range(_T_):
	(n,) = read()
	gr = [[] for i in range(n)]
	vis = [False for i in range(n)]
	for i in range(n - 1):
		(x, y) = read()
		x -= 1
		y -= 1
		gr[x].append(y)
		gr[y].append(x)
	(cent, size) = centroid(gr)
	if len(cent) == 1:
		print(x + 1, y + 1)
		print(x + 1, y + 1)
	else:
		opponent = -1
		maxsize = -12
		to_remove = -1
		for node in cent:
			for nei in gr[node]:
				if size[nei] > maxsize and nei not in cent:
					maxsize = size[nei]
					opponent = node
					to_remove = nei
		if opponent == cent[0]:
			print(cent[0] + 1, to_remove + 1)
			print(cent[1] + 1, to_remove + 1)
		else:
			print(cent[1] + 1, to_remove + 1)
			print(cent[0] + 1, to_remove + 1)


from collections import defaultdict

def dfs(node):
	stack = [node]
	visited = defaultdict(int)
	visited[node] = node
	for i in stack:
		for j in tree[i]:
			if visited[j] == 0:
				visited[j] = i
				stack.append(j)
	children = [1] * (n + 1)
	while len(stack) > 1:
		i = stack.pop()
		children[visited[i]] += children[i]
	return (visited, children)
for _ in range(int(input())):
	n = int(input())
	tree = defaultdict(list)
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		tree[u].append(v)
		tree[v].append(u)
	if n % 2:
		print(1, tree[1][0])
		print(1, tree[1][0])
		continue
	(parent, children) = dfs(1)
	mid = n // 2
	edge = []
	for i in range(2, n + 1):
		if children[i] == mid:
			edge = [i, parent[i]]
			break
	if edge:
		other = 0
		for i in tree[edge[1]]:
			if i != edge[0]:
				other = i
				break
		print(edge[1], other)
		print(edge[0], other)
	else:
		print(1, tree[1][0])
		print(1, tree[1][0])


from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc
import sys, math
input = sys.stdin.readline
t = int(input())

@bootstrap
def numberOfNodes(s, e):
	count1[s] = 1
	for u in graph[s]:
		if u == e:
			continue
		yield numberOfNodes(u, s)
		count1[s] += count1[u]
	yield

@bootstrap
def getMaxNodes(s, e):
	for u in graph[s]:
		if u == e:
			continue
		count2[s] = max(count2[s], count1[u])
		yield getMaxNodes(u, s)
	if e != -1:
		count2[s] = max(count2[s], n - count1[s])
	yield
leaf = 0

@bootstrap
def findLeaf(s, e, val):
	global leaf
	if len(graph[s]) == 1:
		leaf = s
		yield
	for u in graph[s]:
		if u == e or u == val:
			continue
		yield findLeaf(u, s, val)
	yield
for r in range(t):
	n = int(input())
	graph = []
	for i in range(n):
		graph.append([])
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		u -= 1
		v -= 1
		graph[u].append(v)
		graph[v].append(u)
	count1 = [0] * n
	numberOfNodes(0, -1)
	count2 = [0] * n
	getMaxNodes(0, -1)
	centroidVal = min(count2)
	flag = True
	counter = 0
	for i in count2:
		if i == centroidVal:
			if counter > 0:
				flag = False
				break
			else:
				counter += 1
	if flag == True:
		print(1, graph[0][0] + 1)
		print(1, graph[0][0] + 1)
	else:
		centroids = []
		for i in range(n):
			if count2[i] == centroidVal:
				centroids.append(i)
		centroid1 = centroids[0]
		centroid2 = centroids[1]
		findLeaf(centroid1, -1, centroid2)
		print(graph[leaf][0] + 1, leaf + 1)
		print(centroid2 + 1, leaf + 1)


mod = 1000000007
eps = 10 ** (-9)

def main():
	import sys
	from collections import deque
	input = sys.stdin.buffer.readline
	for _ in range(int(input())):
		N = int(input())
		adj = [[] for _ in range(N + 1)]
		for _ in range(N - 1):
			(a, b) = map(int, input().split())
			adj[a].append(b)
			adj[b].append(a)
		que = deque()
		que.append(1)
		seen = [-1] * (N + 1)
		seen[1] = 0
		par = [0] * (N + 1)
		child = [[] for _ in range(N + 1)]
		seq = []
		while que:
			v = que.popleft()
			seq.append(v)
			for u in adj[v]:
				if seen[u] == -1:
					seen[u] = seen[v] + 1
					par[u] = v
					child[v].append(u)
					que.append(u)
		seq.reverse()
		size = [1] * (N + 1)
		a = -1
		b = -1
		for v in seq:
			for u in child[v]:
				size[v] += size[u]
				if size[u] == N // 2 and N % 2 == 0:
					a = v
					b = u
		if a == b == -1:
			a = seq[0]
			b = par[a]
			print(a, b)
			print(a, b)
		else:
			while child[b]:
				b = child[b][0]
			print(b, par[b])
			print(a, b)
main()


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from math import gcd, ceil

def pre(s):
	n = len(s)
	pi = [0] * n
	for i in range(1, n):
		j = pi[i - 1]
		while j and s[i] != s[j]:
			j = pi[j - 1]
		if s[i] == s[j]:
			j += 1
		pi[i] = j
	return pi

def prod(a):
	ans = 1
	for each in a:
		ans = ans * each
	return ans

def lcm(a, b):
	return a * b // gcd(a, b)

def binary(x, length=16):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y

def centroid_decomposition(graph):
	n = len(graph)
	bfs = [n - 1]
	for node in bfs:
		bfs += graph[node]
		for nei in graph[node]:
			graph[nei].remove(node)
	size = [0] * n
	for node in reversed(bfs):
		size[node] = 1 + sum((size[child] for child in graph[node]))

	def reroot_centroid(root):
		N = size[root]
		while True:
			for child in graph[root]:
				if size[child] > N // 2:
					size[root] = N - size[child]
					graph[root].remove(child)
					graph[child].append(root)
					root = child
					break
			else:
				return root
	bfs = [n - 1]
	for node in bfs:
		centroid = reroot_centroid(node)
		bfs += graph[centroid]
		return centroid

def dfs(graph, start=0):
	n = len(graph)
	dp = [0] * n
	(visited, finished) = ([False] * n, [False] * n)
	stack = [start]
	while stack:
		start = stack[-1]
		if not visited[start]:
			visited[start] = True
			for child in graph[start]:
				if not visited[child]:
					stack.append(child)
		else:
			stack.pop()
			dp[start] += 1
			for child in graph[start]:
				if finished[child]:
					dp[start] += dp[child]
			finished[start] = True
	return (visited, dp)
for _ in range(int(input()) if True else 1):
	n = int(input())
	graph = [[] for i in range(n + 1)]
	for i in range(n - 1):
		(x, y) = map(int, input().split())
		graph[x] += [y]
		graph[y] += [x]
	graph2 = [list(graphh) for graphh in graph]
	centroid1 = centroid_decomposition(graph)
	graph = [list(k) for k in graph2]
	(visited, dp) = dfs(graph, centroid1)
	x = dp[centroid1]
	dp[centroid1] = 0
	ma = max(dp)
	if 2 * ma == x:
		centroid2 = dp.index(ma)
		for i in graph[centroid1]:
			if i != centroid2:
				print(i, centroid1)
				print(i, centroid2)
				break
	else:
		print(1, graph[1][0])
		print(1, graph[1][0])


import sys

def minp():
	return sys.stdin.readline().strip()

def mint():
	return int(minp())

def mints():
	return map(int, minp().split())

def solve():
	n = mint()
	e = [[] for i in range(n + 1)]
	for i in range(n - 1):
		(x, y) = mints()
		e[x].append(y)
		e[y].append(x)
	q = [None] * (n + 1)
	d = [None] * (n + 1)
	q[0] = (1, -1)
	qr = 1
	ql = 0
	while ql < qr:
		(x, p) = q[ql]
		ql += 1
		for v in e[x]:
			if v != p:
				q[qr] = (v, x)
				qr += 1
	cen = None
	best_com = int(1000000000.0)
	for i in range(qr - 1, -1, -1):
		(x, p) = q[i]
		c = 1
		com = 0
		for v in e[x]:
			if v != p:
				c += d[v]
				com = max(com, d[v])
		com = max(com, n - c)
		d[x] = c
		if com < best_com:
			best_com = com
			cen = [(x, p)]
		elif com == best_com:
			cen.append((x, p))
	if len(cen) == 1:
		print(1, e[1][0])
		print(1, e[1][0])
	else:
		(x, p) = cen[0]
		(x1, p1) = cen[1]
		for v in e[x1]:
			if x != v:
				print(x1, v)
				print(x, v)
				return
for i in range(mint()):
	solve()


import math
import random
import heapq, bisect
import sys
from collections import deque, defaultdict
from fractions import Fraction
import sys
import threading
from collections import defaultdict
threading.stack_size(10 ** 8)
mod = 10 ** 9 + 7
mod1 = 998244353
import os
import sys
from io import BytesIO, IOBase
sys.setrecursionlimit(300000)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

class TreeNode:

	def __init__(self, k, v):
		self.key = k
		self.value = v
		self.left = None
		self.right = None
		self.parent = None
		self.height = 1
		self.num_left = 1
		self.num_total = 1

class AvlTree:

	def __init__(self):
		self._tree = None

	def add(self, k, v):
		if not self._tree:
			self._tree = TreeNode(k, v)
			return
		node = self._add(k, v)
		if node:
			self._rebalance(node)

	def _add(self, k, v):
		node = self._tree
		while node:
			if k < node.key:
				if node.left:
					node = node.left
				else:
					node.left = TreeNode(k, v)
					node.left.parent = node
					return node.left
			elif node.key < k:
				if node.right:
					node = node.right
				else:
					node.right = TreeNode(k, v)
					node.right.parent = node
					return node.right
			else:
				node.value = v
				return

	@staticmethod
	def get_height(x):
		return x.height if x else 0

	@staticmethod
	def get_num_total(x):
		return x.num_total if x else 0

	def _rebalance(self, node):
		n = node
		while n:
			lh = self.get_height(n.left)
			rh = self.get_height(n.right)
			n.height = max(lh, rh) + 1
			balance_factor = lh - rh
			n.num_total = 1 + self.get_num_total(n.left) + self.get_num_total(n.right)
			n.num_left = 1 + self.get_num_total(n.left)
			if balance_factor > 1:
				if self.get_height(n.left.left) < self.get_height(n.left.right):
					self._rotate_left(n.left)
				self._rotate_right(n)
			elif balance_factor < -1:
				if self.get_height(n.right.right) < self.get_height(n.right.left):
					self._rotate_right(n.right)
				self._rotate_left(n)
			else:
				n = n.parent

	def _remove_one(self, node):
		replacement = node.left or node.right
		if node.parent:
			if AvlTree._is_left(node):
				node.parent.left = replacement
			else:
				node.parent.right = replacement
			replacement.parent = node.parent
			node.parent = None
		else:
			self._tree = replacement
			replacement.parent = None
		node.left = None
		node.right = None
		node.parent = None
		self._rebalance(replacement)

	def _remove_leaf(self, node):
		if node.parent:
			if AvlTree._is_left(node):
				node.parent.left = None
			else:
				node.parent.right = None
			self._rebalance(node.parent)
		else:
			self._tree = None
		node.parent = None
		node.left = None
		node.right = None

	def remove(self, k):
		node = self._get_node(k)
		if not node:
			return
		if AvlTree._is_leaf(node):
			self._remove_leaf(node)
			return
		if node.left and node.right:
			nxt = AvlTree._get_next(node)
			node.key = nxt.key
			node.value = nxt.value
			if self._is_leaf(nxt):
				self._remove_leaf(nxt)
			else:
				self._remove_one(nxt)
			self._rebalance(node)
		else:
			self._remove_one(node)

	def get(self, k):
		node = self._get_node(k)
		return node.value if node else -1

	def _get_node(self, k):
		if not self._tree:
			return None
		node = self._tree
		while node:
			if k < node.key:
				node = node.left
			elif node.key < k:
				node = node.right
			else:
				return node
		return None

	def get_at(self, pos):
		x = pos + 1
		node = self._tree
		while node:
			if x < node.num_left:
				node = node.left
			elif node.num_left < x:
				x -= node.num_left
				node = node.right
			else:
				return (node.key, node.value)
		raise IndexError('Out of ranges')

	@staticmethod
	def _is_left(node):
		return node.parent.left and node.parent.left == node

	@staticmethod
	def _is_leaf(node):
		return node.left is None and node.right is None

	def _rotate_right(self, node):
		if not node.parent:
			self._tree = node.left
			node.left.parent = None
		elif AvlTree._is_left(node):
			node.parent.left = node.left
			node.left.parent = node.parent
		else:
			node.parent.right = node.left
			node.left.parent = node.parent
		bk = node.left.right
		node.left.right = node
		node.parent = node.left
		node.left = bk
		if bk:
			bk.parent = node
		node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
		node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
		node.num_left = 1 + self.get_num_total(node.left)

	def _rotate_left(self, node):
		if not node.parent:
			self._tree = node.right
			node.right.parent = None
		elif AvlTree._is_left(node):
			node.parent.left = node.right
			node.right.parent = node.parent
		else:
			node.parent.right = node.right
			node.right.parent = node.parent
		bk = node.right.left
		node.right.left = node
		node.parent = node.right
		node.right = bk
		if bk:
			bk.parent = node
		node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
		node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
		node.num_left = 1 + self.get_num_total(node.left)

	@staticmethod
	def _get_next(node):
		if not node.right:
			return node.parent
		n = node.right
		while n.left:
			n = n.left
		return n

class SegmentTree1:

	def __init__(self, data, default=2 ** 51, func=lambda a, b: a & b):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class SegmentTree:

	def __init__(self, data, default=0, func=lambda a, b: a + b):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class Factorial:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorials = [1, 1]
		self.invModulos = [0, 1]
		self.invFactorial_ = [1, 1]

	def calc(self, n):
		if n <= -1:
			print('Invalid argument to calculate n!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.factorials):
			return self.factorials[n]
		nextArr = [0] * (n + 1 - len(self.factorials))
		initialI = len(self.factorials)
		prev = self.factorials[-1]
		m = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * i % m
		self.factorials += nextArr
		return self.factorials[n]

	def inv(self, n):
		if n <= -1:
			print('Invalid argument to calculate n^(-1)')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		p = self.MOD
		pi = n % p
		if pi < len(self.invModulos):
			return self.invModulos[pi]
		nextArr = [0] * (n + 1 - len(self.invModulos))
		initialI = len(self.invModulos)
		for i in range(initialI, min(p, n + 1)):
			next = -self.invModulos[p % i] * (p // i) % p
			self.invModulos.append(next)
		return self.invModulos[pi]

	def invFactorial(self, n):
		if n <= -1:
			print('Invalid argument to calculate (n^(-1))!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.invFactorial_):
			return self.invFactorial_[n]
		self.inv(n)
		nextArr = [0] * (n + 1 - len(self.invFactorial_))
		initialI = len(self.invFactorial_)
		prev = self.invFactorial_[-1]
		p = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * self.invModulos[i % p] % p
		self.invFactorial_ += nextArr
		return self.invFactorial_[n]

class Combination:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorial = Factorial(MOD)

	def ncr(self, n, k):
		if k < 0 or n < k:
			return 0
		k = min(k, n - k)
		f = self.factorial
		return f.calc(n) * f.invFactorial(max(n - k, k)) * f.invFactorial(min(k, n - k)) % self.MOD

def powm(a, n, m):
	if a == 1 or n == 0:
		return 1
	if n % 2 == 0:
		s = powm(a, n // 2, m)
		return s * s % m
	else:
		return a * powm(a, n - 1, m) % m

def sort_list(list1, list2):
	zipped_pairs = zip(list2, list1)
	z = [x for (_, x) in sorted(zipped_pairs)]
	return z

def product(l):
	por = 1
	for i in range(len(l)):
		por *= l[i]
	return por

def binarySearchCount(arr, n, key):
	left = 0
	right = n - 1
	count = 0
	while left <= right:
		mid = int((right + left) / 2)
		if arr[mid] < key:
			count = mid + 1
			left = mid + 1
		else:
			right = mid - 1
	return count

def countdig(n):
	c = 0
	while n > 0:
		n //= 10
		c += 1
	return c

def binary(x, length):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y

def countGreater(arr, n, k):
	l = 0
	r = n - 1
	leftGreater = n
	while l <= r:
		m = int(l + (r - l) / 2)
		if arr[m] >= k:
			leftGreater = m
			r = m - 1
		else:
			l = m + 1
	return n - leftGreater

def main():
	for ik in range(int(input())):
		n = int(input())
		graph = defaultdict(list)
		visited = [False] * n
		sub = [0] * n
		cen = []

		def dfssub(v):
			visited[v] = True
			c = 1
			for i in graph[v]:
				if visited[i] == False:
					c += dfssub(i)
			sub[v] = c
			return c

		def dfs(v):
			visited[v] = True
			f = 0
			for i in graph[v]:
				if visited[i] == False:
					dfs(i)
					if sub[i] > n // 2:
						f = 1
			if n - sub[v] > n // 2:
				f = 1
			if f == 0:
				cen.append(v)
		for i in range(n - 1):
			(a, b) = map(int, input().split())
			graph[a - 1].append(b - 1)
			graph[b - 1].append(a - 1)
		dfssub(0)
		visited = [False] * n
		dfs(0)
		if len(cen) == 1:
			print(1, graph[0][0] + 1)
			print(1, graph[0][0] + 1)
			continue
		for i in graph[cen[0]]:
			if cen[1] != i:
				print(cen[0] + 1, i + 1)
				print(cen[1] + 1, i + 1)
				break
t = threading.Thread(target=main)
t.start()
t.join()


for _ in range(int(input())):
	n = int(input())
	(ee, cc, pp, mcc) = ([[] for _ in range(n + 1)], [1] * (n + 1), [0] * (n + 1), [0] * (n + 1))
	q = [-1, 1]
	vs = {1}
	for _ in range(n - 1):
		(u, v) = map(int, input().split())
		ee[u].append(v)
		ee[v].append(u)
	while q:
		u = q.pop()
		if u < 0:
			u = -u
			p = pp[u]
			cc[p] += cc[u]
			mcc[p] = max(mcc[p], cc[u])
			mcc[u] = max(mcc[u], n - cc[u])
			continue
		for v in ee[u]:
			if v not in vs:
				pp[v] = u
				q.append(-v)
				q.append(v)
				vs.add(v)
	mcc[0] = n
	mmcc = min(mcc)
	cen = [x for x in range(n + 1) if mcc[x] == mmcc]
	if len(cen) == 1:
		print(f'1 {ee[1][0]}')
		print(f'1 {ee[1][0]}')
		continue
	(x, y) = cen[:2]
	i = 0
	if pp[y] == x:
		(x, y) = (y, x)
	if ee[y][0] == x:
		i = 1
	print(f'{y} {ee[y][i]}')
	print(f'{x} {ee[y][i]}')


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def RL():
	return map(int, sys.stdin.readline().rstrip().split())

def RLL():
	return list(RL())

def N():
	return int(input())

def comb(n, m):
	return factorial(n) / (factorial(m) * factorial(n - m)) if n >= m else 0

def perm(n, m):
	return factorial(n) // factorial(n - m) if n >= m else 0

def mdis(x1, y1, x2, y2):
	return abs(x1 - x2) + abs(y1 - y2)

def toord(c):
	return ord(c) - ord('a')

def lcm(a, b):
	return a * b // gcd(a, b)
mod = 998244353
INF = float('inf')
from math import factorial, sqrt, ceil, floor, gcd
from collections import Counter, defaultdict, deque
from heapq import heapify, heappop, heappush
from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

def main():
	for _ in range(N()):
		n = N()
		gp = [[] for _ in range(n + 1)]
		for _ in range(n - 1):
			(f, t) = RL()
			gp[f].append(t)
			gp[t].append(f)
		res = (-1, -1)
		num = 0

		@bootstrap
		def dfs(node, par):
			nonlocal res, num
			size = 1
			for nex in gp[node]:
				if nex == par:
					continue
				size += (yield dfs(nex, node))
			if size >= n / 2 and res == (-1, -1):
				res = (node, par)
				num = size
			yield size
		dfs(1, -1)
		if -1 in res:
			print(1, gp[1][0])
			print(1, gp[1][0])
			continue
		if num * 2 != n:
			print(*res)
			print(*res)
		else:
			for nex in gp[res[0]]:
				if nex != res[1]:
					print(nex, res[0])
					print(nex, res[1])
					break
main()


from collections import *
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def dfs(x):
	vis[x] = 1
	stack = []
	stack.append(x)
	count = 0
	while len(stack) != N:
		s = stack[count]
		for i in range(len(adj[s])):
			t = adj[s][i]
			if vis[t] == 0:
				parent[t] = s
				vis[t] = 1
				val[t] = 1
				stack.append(t)
		count += 1
	while len(stack) != 0:
		r = stack.pop()
		val[parent[r]] += val[r]
for _ in range(int(input())):
	N = int(input())
	adj = defaultdict(list)
	for i in range(N - 1):
		(x, y) = list(map(int, input().split()))
		adj[x].append(y)
		adj[y].append(x)
	vis = [0] * (N + 1)
	parent = [0] * (N + 1)
	val = [0] * (N + 1)
	val[1] = 1
	dfs(1)
	anslist = []
	for i in range(1, N + 1):
		ans = -1
		for j in range(len(adj[i])):
			if adj[i][j] != parent[i]:
				ans = max(ans, val[adj[i][j]])
		ans = max(ans, N - val[i])
		anslist.append([ans, i])
	anslist.sort()
	if anslist[0][0] != anslist[1][0]:
		node = anslist[0][1]
		next1 = adj[node][0]
		print(node, next1)
		print(node, next1)
	else:
		node1 = anslist[0][1]
		node2 = anslist[1][1]
		for i in range(len(adj[node1])):
			next1 = adj[node1][i]
			if next1 != node2:
				save = next1
				break
		print(node1, save)
		print(node2, save)


import sys
input = sys.stdin.readline
(T,) = map(int, input().split())
for _ in range(T):
	(N,) = map(int, input().split())
	G = [set() for _ in range(N + 1)]
	d = [set() for _ in range(N + 1)]
	for _ in range(N - 1):
		(a, b) = map(int, input().split())
		G[a].add(b)
		G[b].add(a)
	stack = [1]
	vs = set([1])
	vs_dfs = list()
	parents = [0] * (N + 1)
	while stack:
		v = stack.pop()
		vs_dfs.append(v)
		for u in G[v]:
			if u in vs:
				continue
			parents[u] = v
			d[v].add(u)
			vs.add(u)
			stack.append(u)
	size = [1] * (N + 1)
	for v in vs_dfs[::-1]:
		for u in d[v]:
			size[v] += size[u]
	stack = [1]
	vs = set([1])
	R = 0
	while stack:
		v = stack.pop()
		m = 0
		for u in d[v]:
			m = max(size[u], m)
			stack.append(u)
		m = max(N - size[v], m)
		if m * 2 <= N:
			R = v
			break
	R2 = 0
	for v in d[R]:
		m = 0
		for u in d[v]:
			max(size[u], m)
		m = max(N - size[v], m)
		if m * 2 <= N:
			R2 = v
			break
	if R2 == 0:
		u = d[1].pop()
		print(1, u)
		print(1, u)
	else:
		stack = [R2]
		f = 0
		while stack:
			v = stack.pop()
			for u in d[v]:
				stack.append(u)
				if not d[u]:
					f = 1
					break
			if f:
				break
		print(v, u)
		print(R, u)


from random import choice as _choice
import sys as _sys

def main():
	t = int(input())
	for i in range(t):
		(n,) = _read_ints()
		graph = [set() for v in range(n)]
		for i_edge in range(n - 1):
			(v1, v2) = _read_ints()
			v1 -= 1
			v2 -= 1
			graph[v1].add(v2)
			graph[v2].add(v1)
		operations = find_operations_necessary_to_remain_one_centroid(graph)
		for (v1, v2) in operations:
			print(v1 + 1, v2 + 1)

def _read_line():
	result = _sys.stdin.readline()
	assert result[-1] == '\n'
	return result[:-1]

def _read_ints():
	return map(int, _read_line().split(' '))

def find_operations_necessary_to_remain_one_centroid(graph):
	assert len(graph) > 2
	graph = [set(neighbors) for neighbors in graph]
	centroids = find_centroids(graph)
	assert 0 < len(centroids) <= 2
	if len(centroids) == 1:
		operation_remove = (0, tuple(graph[0])[0])
		operation_add = operation_remove
	else:
		assert len(centroids) == 2
		(centroid_1, centroid_2) = centroids
		vertex_to_move = centroid_1
		forbidden_vertex = centroid_2
		while len(graph[vertex_to_move]) != 1:
			neighbors = tuple(graph[vertex_to_move])
			new_vertex_to_move = neighbors[0]
			if new_vertex_to_move == forbidden_vertex:
				new_vertex_to_move = neighbors[1]
			forbidden_vertex = vertex_to_move
			vertex_to_move = new_vertex_to_move
		vertex_to_move_parent = tuple(graph[vertex_to_move])[0]
		operation_remove = (vertex_to_move, vertex_to_move_parent)
		graph[vertex_to_move].remove(vertex_to_move_parent)
		graph[vertex_to_move_parent].remove(vertex_to_move)
		assert len(graph[vertex_to_move]) == 0
		new_parent = centroid_2
		graph[vertex_to_move].add(new_parent)
		graph[new_parent].add(vertex_to_move)
		operation_add = (vertex_to_move, new_parent)
	return (operation_remove, operation_add)

def find_centroids(graph):
	vertices_n = len(graph)
	vertices_values = [None] * len(graph)
	leaves = [vertex for vertex in range(len(graph)) if len(graph[vertex]) == 1]
	vertices_accumulated = [None] * len(graph)
	for leave in leaves:
		vertices_accumulated[leave] = 1
		vertices_values[leave] = vertices_n - 1
	active = set().union(*(graph[leave] for leave in leaves))
	passed = set(leaves)
	active -= passed
	while len(passed) < len(graph):
		old_active = active
		active = set()
		for vertex in old_active:
			neighbors = graph[vertex]
			neighbors_not_passed = neighbors - passed
			if len(neighbors_not_passed) > 1:
				active.add(vertex)
				continue
			vertices_accumulated[vertex] = sum((vertices_accumulated[neighbor] for neighbor in neighbors if neighbor in passed)) + 1
			components_remain_sizes = []
			for neighbor in neighbors - neighbors_not_passed:
				components_remain_sizes.append(vertices_accumulated[neighbor])
			assert len(neighbors_not_passed) <= 1
			for neighbor in neighbors_not_passed:
				components_remain_sizes.append(vertices_n - vertices_accumulated[vertex])
			vertex_value = max(components_remain_sizes)
			vertices_values[vertex] = vertex_value
			passed.add(vertex)
			active.update(neighbors_not_passed)
		active = active - passed
	centroid_value = min(vertices_values)
	centroids = [vertex for (vertex, value) in enumerate(vertices_values) if value == centroid_value]
	return centroids
main()


import sys
input = sys.stdin.readline
t = int(input())
for tests in range(t):
	N = int(input())
	E = [[] for i in range(N + 1)]
	for i in range(N - 1):
		(x, y) = map(int, input().split())
		E[x].append(y)
		E[y].append(x)
	ROOT = 1
	QUE = [ROOT]
	Parent = [-1] * (N + 1)
	Parent[ROOT] = N + 1
	TOP_SORT = []
	while QUE:
		x = QUE.pop()
		TOP_SORT.append(x)
		for to in E[x]:
			if Parent[to] == -1:
				Parent[to] = x
				QUE.append(to)
	Children = [1] * (N + 1)
	CC = [0] * (N + 1)
	for x in TOP_SORT[1:][::-1]:
		Children[Parent[x]] += Children[x]
		CC[Parent[x]] = max(CC[Parent[x]], Children[x])
	for i in range(1, N + 1):
		CC[i] = max(CC[i], N - Children[i])
	MIN = min(CC[1:])
	CLIST = []
	for i in range(1, N + 1):
		if CC[i] == MIN:
			CLIST.append(i)
	if len(CLIST) == 1:
		y = E[1][0]
		print(1, y)
		print(1, y)
	else:
		x = CLIST[0]
		y = CLIST[1]
		for j in E[x]:
			if j == y:
				continue
			else:
				z = j
				break
		print(x, z)
		print(y, z)


import sys
input = sys.stdin.buffer.readline

class UnionFind:

	def __init__(self, n):
		self.parent = [-1] * n
		self.n = n
		self.cnt = n

	def root(self, x):
		if self.parent[x] < 0:
			return x
		else:
			self.parent[x] = self.root(self.parent[x])
			return self.parent[x]

	def merge(self, x, y):
		x = self.root(x)
		y = self.root(y)
		if x == y:
			return False
		if self.parent[x] > self.parent[y]:
			(x, y) = (y, x)
		self.parent[x] += self.parent[y]
		self.parent[y] = x
		self.cnt -= 1
		return True

	def is_same(self, x, y):
		return self.root(x) == self.root(y)

	def size(self, x):
		return -self.parent[self.root(x)]

	def count(self):
		return self.cnt

	def groups(self):
		res = [[] for _ in range(self.n)]
		for i in range(self.n):
			res[self.root(i)].append(i)
		return [group for group in res if group]

def topological_sorted(tree, root=None):
	n = len(tree)
	par = [-1] * n
	tp_order = []
	for v in range(n):
		if par[v] != -1 or (root is not None and v != root):
			continue
		stack = [v]
		while stack:
			v = stack.pop()
			tp_order.append(v)
			for nxt_v in tree[v]:
				if nxt_v == par[v]:
					continue
				par[nxt_v] = v
				stack.append(nxt_v)
	return (tp_order, par)

def centroid(tree):
	n = len(tree)
	(tp_order, par) = topological_sorted(tree, root=None)
	sub_size = [0] * n
	res = []
	for v in tp_order[::-1]:
		is_centroid = True
		sub_size[v] = 1
		for nxt_v in tree[v]:
			if nxt_v == par[v]:
				continue
			if sub_size[nxt_v] > n // 2:
				is_centroid = False
			sub_size[v] += sub_size[nxt_v]
		if is_centroid and n - sub_size[v] <= n // 2:
			res.append(v)
	return res
t = int(input())
for _ in range(t):
	n = int(input())
	info = [list(map(int, input().split())) for i in range(n - 1)]
	tree = [[] for i in range(n)]
	for (u, v) in info:
		u -= 1
		v -= 1
		tree[u].append(v)
		tree[v].append(u)
	root = 0
	cands = centroid(tree)
	if len(cands) == 1:
		print(*info[0])
		print(*info[0])
	else:
		(v1, v2) = (cands[0], cands[1])
		for u1 in tree[v1]:
			if u1 == v2:
				continue
			else:
				break
		print(v1 + 1, u1 + 1)
		print(v2 + 1, u1 + 1)


import sys, os, io
input = sys.stdin.readline
T = int(input())

def dfs(start):
	stack = [start]
	parent = [N] * N
	parent[start] = -1
	cnts = [1] * N
	while stack:
		v = stack[-1]
		ans = marker = 0
		for u in edge[v]:
			if u == parent[v]:
				continue
			if parent[u] == N:
				marker = 1
				parent[u] = v
				stack.append(u)
			else:
				ans = max(ans, cnts[u])
				cnts[v] += cnts[u]
		if marker == 0:
			stack.pop()
			ans = max(ans, N - cnts[v])
			if ans == N // 2:
				lis.append(v)
	return
for t in range(T):
	N = int(input())
	edge = [[] for _ in range(N)]
	for i in range(N - 1):
		(a, b) = map(int, input().split())
		if i == 0:
			edges = [a, b]
		edge[a - 1].append(b - 1)
		edge[b - 1].append(a - 1)
	if N % 2 == 1:
		print(*edges)
		print(*edges)
	else:
		lis = []
		dfs(0)
		if len(lis) <= 1:
			print(*edges)
			print(*edges)
		else:
			for l in edge[lis[0]]:
				if l != lis[1]:
					print(lis[0] + 1, l + 1)
					print(lis[1] + 1, l + 1)
					break


import sys
import threading

def dfs(v, visited, neighbours, level, centroid, parent, s, n):
	visited[v] = True
	smax = 0
	for u in neighbours[v]:
		if not visited[u]:
			level[u] = level[v] + 1
			parent[u] = v
			dfs(u, visited, neighbours, level, centroid, parent, s, n)
			s[v] += s[u]
			smax = max(smax, s[u])
	smax = max(n - s[v], smax)
	if smax <= n / 2:
		centroid.append(v)

def dfs2(v, vis, neighbours):
	vis[v] = True
	child = 0
	for u in neighbours[v]:
		if not vis[u]:
			child += 1
			return dfs2(u, vis, neighbours)
	if child == 0:
		return v

def main():
	for _ in range(int(input())):
		n = int(input())
		visited = [False] * (n + 1)
		level = [0] * (n + 1)
		s = [1] * (n + 1)
		parent = [0] * (n + 1)
		centroid = []
		neighbours = [[] for _ in range(n + 1)]
		for _ in range(n - 1):
			(x, y) = map(int, input().split())
			neighbours[x].append(y)
			neighbours[y].append(x)
		for v in range(1, n + 1):
			if not visited[v]:
				dfs(v, visited, neighbours, level, centroid, parent, s, n)
		if len(centroid) == 1:
			print(centroid[0], neighbours[centroid[0]][0])
			print(centroid[0], neighbours[centroid[0]][0])
		else:
			c1 = centroid[0]
			c2 = centroid[1]
			if level[c1] < level[c2]:
				(c1, c2) = (c2, c1)
			vis = [False] * (n + 1)
			vis[parent[c1]] = True
			leaf = dfs2(c1, vis, neighbours)
			print(parent[leaf], leaf)
			print(c2, leaf)
max_recur_size = 10 ** 5 * 2 + 1000
max_stack_size = max_recur_size * 500
sys.setrecursionlimit(max_recur_size)
threading.stack_size(max_stack_size)
thread = threading.Thread(target=main)
thread.start()


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def RL():
	return map(int, sys.stdin.readline().rstrip().split())

def RLL():
	return list(map(int, sys.stdin.readline().rstrip().split()))

def N():
	return int(input())

def print_list(l):
	print(' '.join(map(str, l)))
from collections import defaultdict as dc
for _ in range(N()):
	n = N()
	dic = dc(list)
	for _ in range(n - 1):
		(u, v) = RL()
		dic[u].append(v)
		dic[v].append(u)
	father = [0] * (n + 1)
	child = dc(list)
	now = [1]
	while now:
		node = now.pop()
		for c in dic[node]:
			if c not in child:
				child[node].append(c)
				father[c] = node
				now.append(c)
	count = [1] * (n + 1)
	gress = [0] * (n + 1)
	now = []
	for node in range(1, n + 1):
		gress[node] = len(child[node])
		if gress[node] == 0:
			now.append(node)
	while now:
		node = now.pop()
		for c in child[node]:
			count[node] += count[c]
		gress[father[node]] -= 1
		if gress[father[node]] == 0:
			now.append(father[node])
	for i in range(1, n + 1):
		(m, ind) = max([(count[c], c) for c in child[i]] + [(n - count[i], father[i])])
		if m * 2 < n:
			print(i, ind)
			print(i, ind)
			break
		elif m * 2 == n:
			k = -1
			for c in child[i]:
				if c != ind:
					k = c
					break
			if k == -1:
				k = father[i]
			print(i, k)
			print(ind, k)
			break


import sys
sys.setrecursionlimit(10 ** 9)
import threading
threading.stack_size(67108864)
INF = 10 ** 9
min_size = INF
min_size_vertices = []

def input():
	return sys.stdin.readline().rstrip()

def addEdgeListToAdjList(edgeList, adjList, isDirectedGraph=False):
	for edge in edgeList:
		adjList[edge[0]].append(edge[1])
		if isDirectedGraph == False:
			adjList[edge[1]].append(edge[0])

def dfs(startVertex, adjList, isVisited):
	global min_size
	global min_size_vertices
	isVisited[startVertex] = True
	n = len(adjList) - 1
	totalVerticesInSubTree = 1
	maxi_childSubTreeSize = 0
	for vertex in adjList[startVertex]:
		if isVisited[vertex] == False:
			count = dfs(vertex, adjList, isVisited)
			maxi_childSubTreeSize = max(maxi_childSubTreeSize, count)
			totalVerticesInSubTree += count
	maxi_childSubTreeSize = max(maxi_childSubTreeSize, n - totalVerticesInSubTree)
	if maxi_childSubTreeSize < min_size:
		min_size = maxi_childSubTreeSize
		min_size_vertices = [startVertex]
	elif maxi_childSubTreeSize == min_size:
		min_size_vertices.append(startVertex)
	return totalVerticesInSubTree

def main():
	global min_size
	global min_size_vertices
	t = int(input())
	for i in range(t):
		min_size = INF
		min_size_vertices = []
		n = int(input())
		edgeList = [list(map(int, input().split())) for i in range(0, n - 1)]
		adjList = [[] for i in range(0, n + 1)]
		isVisited = [False for i in range(0, n + 1)]
		addEdgeListToAdjList(edgeList, adjList)
		dfs(1, adjList, isVisited)
		if len(min_size_vertices) < 2:
			print(' '.join(map(str, edgeList[0])))
			print(' '.join(map(str, edgeList[0])))
		else:
			val1 = min_size_vertices[0]
			val2 = min_size_vertices[1]
			val3 = adjList[val1][0]
			if val3 == val2:
				val3 = adjList[val1][1]
			print(str(val3) + ' ' + str(val1))
			print(str(val3) + ' ' + str(val2))
thread = threading.Thread(target=main)
thread.start()
thread.join()


import sys
input = sys.stdin.readline
T = int(input())
for _ in range(T):
	n = int(input())
	G = {}
	for i in range(1, n + 1):
		G[i] = []
	(xv, yv) = (0, 0)
	LR = []
	for i in range(n - 1):
		(x, y) = map(int, input().split())
		G[x].append(y)
		G[y].append(x)
		LR.append([x, y])
		(xv, yv) = (x, y)
	Fd = [[0] for i in range(n + 1)]
	v = [0 for i in range(n + 1)]
	vis = [0 for i in range(n + 1)]
	Q = [1]
	vis[1] = 1
	A = []
	while len(Q) != 0:
		a = Q.pop()
		A.append(a)
		val = vis[a]
		for i in G[a]:
			if vis[i] == 0:
				vis[i] = val + 1
				Q.append(i)
	A = A[::-1]
	v = max(vis)
	vis1 = [0 for i in range(n + 1)]
	for i in range(n):
		val = A[i]
		if vis[val] == v:
			vis1[val] = 1
		else:
			for i in G[val]:
				if vis1[i] == 1:
					Fd[val].append(sum(Fd[i]) + 1)
			vis1[val] = 1
	cp = []
	val = n
	for i in range(1, n + 1):
		v = max(max(Fd[i]), n - sum(Fd[i]) - 1)
		if v < val:
			cp = [i]
			val = v
		elif v == val:
			cp.append(i)
	if len(cp) == 1:
		print(yv, xv)
		print(yv, xv)
	else:
		val = cp[0]
		yv = 0
		for i in G[val]:
			if i != cp[1]:
				print(val, i)
				print(i, cp[1])
				break


from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc
import sys
input = sys.stdin.buffer.readline

@bootstrap
def findCentroid(node, p):
	size = 1
	componentSizes = []
	for child in adj[node]:
		if child != p:
			x = (yield findCentroid(child, node))
			componentSizes.append(x)
			size += x
	componentSizes.append(n - size)
	nodesWS[max(componentSizes)].append(node)
	yield size

@bootstrap
def getLeaf(node, p):
	if len(adj[node]) == 1:
		yield node
	for child in adj[node]:
		if child != p:
			yield (yield getLeaf(child, node))
t = int(input())
for _ in range(t):
	n = int(input())
	adj = [[] for _a in range(n + 1)]
	for _b in range(n - 1):
		(x, y) = [int(x) for x in input().split()]
		adj[x].append(y)
		adj[y].append(x)
	nodesWS = [[] for _a in range(n + 1)]
	findCentroid(1, 0)
	for i in range(n + 1):
		if len(nodesWS[i]) > 0:
			centroidSize = i
			break
	if len(nodesWS[centroidSize]) == 1:
		(x1, y1) = (1, adj[1][0])
		print('{} {}'.format(x1, y1))
		print('{} {}'.format(x1, y1))
	else:
		(c1, c2) = nodesWS[centroidSize]
		x1 = getLeaf(c1, c2)
		y1 = adj[x1][0]
		print('{} {}'.format(x1, y1))
		print('{} {}'.format(x1, c2))


import sys
input = sys.stdin.readline
from _collections import defaultdict, deque
for _ in range(int(input())):
	n = int(input())
	graph = defaultdict(list)
	for _ in range(n - 1):
		(i, j) = map(int, input().split())
		graph[i].append(j)
		graph[j].append(i)
	stack = deque()
	stack.append(1)
	visited = [0] * (n + 1)
	ord = []
	parent = [0] * (n + 1)
	while stack:
		u = stack.pop()
		visited[u] = 1
		ord.append(u)
		for i in graph[u]:
			if not visited[i]:
				stack.append(i)
				parent[i] = u
	cmp = [1] * (n + 1)
	cnt = [0] * (n + 1)
	for i in ord[1:][::-1]:
		cmp[parent[i]] += cmp[i]
		cnt[parent[i]] = max(cnt[parent[i]], cmp[i])
	for i in range(1, n + 1):
		cnt[i] = max(cnt[i], n - cmp[i])
	mn = min(cnt[1:])
	cmin = []
	for i in range(1, n + 1):
		if cnt[i] == mn:
			cmin.append(i)
	if len(cmin) == 1:
		print(1, graph[1][0])
		print(1, graph[1][0])
	else:
		(l, m) = cmin[:2]
		for i in graph[l]:
			if i != m:
				break
		print(l, i)
		print(m, i)


from collections import defaultdict as dd, deque as dq
import sys
input = sys.stdin.readline

def bfs(tot, val, parent, d):
	q = dq([1])
	while q:
		u = q.pop()
		if u != 1:
			val[u] = max(val[u], n - tot[u] - 1)
		for j in d[u]:
			if j != parent[u]:
				q.appendleft(j)

def dfs(u, vis, prent, d, val, tot):
	st = [u]
	rst = []
	while st:
		u = st.pop()
		vis[u] = 1
		rst.append(u)
		for j in d[u]:
			if vis[j] == 0:
				parent[j] = u
				st.append(j)
				vis[j] = 1
	while rst:
		u = rst.pop()
		for j in d[u]:
			if j != parent[u]:
				tot[u] += tot[j] + 1
				val[u] = max(val[u], tot[j] + 1)
t = int(input())
while t:
	d = dd(list)
	n = int(input())
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		uu = u
		vv = v
		d[u].append(v)
		d[v].append(u)
	parent = [0] * (n + 1)
	vis = [0] * (n + 1)
	val = [0] * (n + 1)
	val[0] = n + 1
	tot = [0] * (n + 1)
	dfs(1, vis, parent, d, val, tot)
	bfs(tot, val, parent, d)
	l = []
	mi = min(val)
	for i in range(1, n + 1):
		if val[i] == mi:
			l.append(i)
	if len(l) == 1:
		print(uu, vv)
		print(uu, vv)
	else:
		a = l[0]
		b = l[1]
		for i in d[a]:
			if i != b:
				print(i, a)
				print(i, b)
				break
	t -= 1


import sys
Case = 1
Case = int(sys.stdin.buffer.readline())

def centroid(g):
	n = len(g)
	centroid = []
	size = [0 for i in range(n)]

	@recursive
	def dfs(node, par):
		size[node] = 1
		iscent = True
		for nei in g[node]:
			if nei != par:
				yield dfs(nei, node)
				size[node] += size[nei]
				if size[nei] > n // 2:
					iscent = False
		if n - size[node] > n // 2:
			iscent = False
		if iscent:
			centroid.append(node)
		yield
	dfs(0, -1)
	return (centroid, size)

def main():
	n = inin()
	gr = [[] for i in range(n)]
	vis = [False for i in range(n)]
	for i in range(n - 1):
		(x, y) = inar()
		x -= 1
		y -= 1
		gr[x].append(y)
		gr[y].append(x)
	(cent, size) = centroid(gr)
	if len(cent) == 1:
		pr(x + 1, y + 1)
		pr(x + 1, y + 1)
	else:
		opponent = -1
		maxsize = -12
		to_remove = -1
		for node in cent:
			for nei in gr[node]:
				if size[nei] > maxsize and nei not in cent:
					maxsize = size[nei]
					opponent = node
					to_remove = nei
		if opponent == cent[0]:
			pr(cent[0] + 1, to_remove + 1)
			pr(cent[1] + 1, to_remove + 1)
		else:
			pr(cent[1] + 1, to_remove + 1)
			pr(cent[0] + 1, to_remove + 1)
import sys
inp = sys.stdin.buffer.readline
inar = lambda : list(map(int, inp().split()))
inin = lambda : int(inp())
inst = lambda : inp().decode().strip()
wrt = sys.stdout.write
pr = lambda *args, end='\n': wrt(' '.join([str(x) for x in args]) + end)
enum = enumerate
from types import GeneratorType

def recursive(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc
inf = float('inf')
for __Case__ in range(Case):
	main()


import os
import sys
import math
from io import BytesIO, IOBase
from fractions import Fraction
import collections
from itertools import permutations
from collections import defaultdict
from collections import deque
import threading
threading.stack_size(10 ** 8)
sys.setrecursionlimit(300000)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def main():
	for ik in range(int(input())):
		n = int(input())
		graph = defaultdict(list)
		visited = [False] * n
		sub = [0] * n
		cen = []

		def dfssub(v):
			visited[v] = True
			c = 1
			for i in graph[v]:
				if visited[i] == False:
					c += dfssub(i)
			sub[v] = c
			return c

		def dfs(v):
			visited[v] = True
			f = 0
			for i in graph[v]:
				if visited[i] == False:
					dfs(i)
					if sub[i] > n // 2:
						f = 1
			if n - sub[v] > n // 2:
				f = 1
			if f == 0:
				cen.append(v)
		for i in range(n - 1):
			(a, b) = map(int, input().split())
			graph[a - 1].append(b - 1)
			graph[b - 1].append(a - 1)
		dfssub(0)
		visited = [False] * n
		dfs(0)
		if len(cen) == 1:
			print(1, graph[0][0] + 1)
			print(1, graph[0][0] + 1)
			continue
		for i in graph[cen[0]]:
			if cen[1] != i:
				print(cen[0] + 1, i + 1)
				print(cen[1] + 1, i + 1)
				break
t = threading.Thread(target=main)
t.start()
t.join()


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
t = int(input())
while t > 0:
	t -= 1

	def graph_undirected():
		n = int(input())
		graph = {}
		for i in range(n - 1):
			(vertex, neighbour) = [int(x) for x in input().split()]
			if vertex in graph:
				graph[vertex].append(neighbour)
			else:
				graph[vertex] = [neighbour]
			if neighbour in graph:
				graph[neighbour].append(vertex)
			else:
				graph[neighbour] = [vertex]
		return (graph, n)
	(graph, n) = graph_undirected()
	dp = [[] for x in range(n + 1)]

	def dfs(graph, n, currnode):
		visited = [False for x in range(n + 1)]
		stack = [currnode]
		while stack:
			currnode = stack[-1]
			if visited[currnode] == False:
				visited[currnode] = True
			for neighbour in graph[currnode]:
				if visited[neighbour] == False:
					visited[neighbour] = True
					stack.append(neighbour)
					break
			else:
				if len(stack) > 1:
					s = sum(dp[stack[-1]])
					dp[stack[-1]].append(n - s - 1)
					dp[stack[-2]].append(s + 1)
				stack.pop()
	dfs(graph, n, 1)
	ans = []
	indexmin = []
	valmin = float('inf')
	for i in range(1, n + 1):
		m = max(dp[i])
		if m < valmin:
			valmin = m
			indexmin.clear()
			indexmin.append(i)
		elif m == valmin:
			indexmin.append(i)
	if len(indexmin) == 1:
		print(indexmin[0], graph[indexmin[0]][0])
		print(indexmin[0], graph[indexmin[0]][0])
	else:
		(a, b) = (indexmin[0], indexmin[1])
		ans = None
		val = float('inf')
		for neighbour in graph[a]:
			if neighbour != b:
				m = max(dp[neighbour])
				if m < val:
					val = m
					ans = neighbour
		print(a, ans)
		print(b, ans)


import sys
input = sys.stdin.readline
from collections import deque
t = int(input())
for _ in range(t):
	n = int(input())
	g = [[] for i in range(n)]
	for i in range(n - 1):
		(u, v) = map(int, input().split())
		g[u - 1].append(v - 1)
		g[v - 1].append(u - 1)
	w = [1] * n
	bfs_order = []
	dq = deque([[-1, 0]])
	par = [-1] * n
	while dq:
		(p, ver) = dq.popleft()
		bfs_order.append(ver)
		for to in g[ver]:
			if to == p:
				continue
			par[to] = ver
			dq.append([ver, to])
	bfs_order.reverse()
	for x in bfs_order:
		if x == 0:
			continue
		w[par[x]] += w[x]
	cen = [0] * n
	for i in range(n):
		for to in g[i]:
			if par[i] != to:
				cen[i] = max(cen[i], w[to])
		cen[i] = max(cen[i], n - w[i])
	val = min(cen)
	idx = []
	for i in range(n):
		if cen[i] == val:
			idx.append(i)
	if len(idx) == 1:
		print(1, g[0][0] + 1)
		print(1, g[0][0] + 1)
	else:
		(x, y) = idx
		if par[x] != y:
			(x, y) = (y, x)
		leaf = -1
		q = [x]
		while q:
			ver = q.pop()
			if len(g[ver]) == 1:
				leaf = ver
			for to in g[ver]:
				if to != par[ver]:
					q.append(to)
		print(leaf + 1, par[leaf] + 1)
		print(leaf + 1, y + 1)


import sys
T = int(sys.stdin.readline().strip())
for t in range(0, T):
	n = int(sys.stdin.readline().strip())
	N = [[] for i in range(0, n)]
	C = [[] for i in range(0, n)]
	for i in range(0, n - 1):
		(x, y) = list(map(int, sys.stdin.readline().strip().split()))
		(x, y) = (x - 1, y - 1)
		N[x].append(y)
		N[y].append(x)
	for i in range(0, n):
		if len(N[i]) == 1:
			x1 = i
			y1 = N[i][0]
	N[x1] = []
	N[y1].remove(x1)
	L = [i for i in range(0, n)]
	while len(L) > 0:
		i = L.pop()
		if len(N[i]) - len(C[i]) == 1:
			s = sum(C[i])
			C[i].append(n - 2 - s)
			for j in N[i]:
				if len(N[j]) - len(C[j]) != 0:
					C[j].append(s + 1)
					if len(N[j]) - len(C[j]) == 1:
						L.append(j)
	C[x1] = [n + 10]
	for i in range(0, n):
		C[i] = max(C[i])
	x2 = C.index(min(C))
	y2 = x1
	print(x1 + 1, y1 + 1)
	print(x2 + 1, y2 + 1)


from sys import setrecursionlimit
setrecursionlimit(10 ** 9)
import threading
threading.stack_size(67108864)

def dfs(v):
	global used, p, mx, n, u
	used[v] = True
	p[v] = 1
	for i in u[v]:
		if not used[i]:
			dfs(i)
			p[v] += p[i]
			mx[v] = max(mx[v], p[i])
	mx[v] = max(mx[v], n - p[v])

def main():
	global used, p, mx, n, u
	gans = []
	for _ in range(int(input())):
		n = int(input())
		u = []
		for i in range(n):
			u.append([])
		aaa = []
		for i in range(n - 1):
			(a, b) = map(lambda x: int(x) - 1, input().split())
			u[a].append(b)
			u[b].append(a)
			if i == 0:
				aaa.append(a + 1)
				aaa.append(b + 1)
		p = [0] * n
		mx = [0] * n
		used = [False] * n
		dfs(0)
		x = min(mx)
		ind = []
		for i in range(n):
			if mx[i] == x:
				ind.append(i)
		if len(ind) == 1:
			gans.append(str(aaa[0]) + ' ' + str(aaa[1]))
			gans.append(str(aaa[0]) + ' ' + str(aaa[1]))
			continue
		a = ind[0]
		b = ind[1]
		if p[a] < p[b]:
			(a, b) = (b, a)
		c = u[b][0]
		if c == a:
			c = u[b][1]
		v1 = (c + 1, b + 1)
		v2 = (a + 1, c + 1)
		gans.append(str(v1[0]) + ' ' + str(v1[1]))
		gans.append(str(v2[0]) + ' ' + str(v2[1]))
	print('\n'.join(gans))
thread = threading.Thread(target=main)
thread.start()
thread.join()


import os
import sys
from io import BytesIO, IOBase
from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc

def DFS(adj):
	parent = {}
	N = len(adj)
	dp = [1] * N
	centroid = [-1] * N

	@bootstrap
	def DFS_use(adj, s):
		sm = 0
		mx = 0
		for i in adj[s]:
			if i not in parent:
				parent[i] = s
				val_sub = (yield DFS_use(adj, i))
				sm += val_sub
				mx = max(mx, val_sub)
		dp[s] += sm
		centroid[s] = max(mx, N - dp[s])
		yield dp[s]
	s = 0
	parent[s] = None
	DFS_use(adj, s)
	return centroid

def find_centroid(adj):
	pass

def main():
	T = iin()
	while T:
		T -= 1
		n = iin()
		adj = [[] for i in range(n)]
		for _ in range(n - 1):
			(i, j) = lin()
			adj[i - 1].append(j - 1)
			adj[j - 1].append(i - 1)
		c1 = DFS(adj)
		c1 = [[c1[i], i] for i in range(n)]
		c1.sort()
		mn = c1[0][0]
		c2 = []
		for (val, idx) in c1:
			if val == mn:
				c2.append(idx)
		ch1 = c2[0]
		sol = [[adj[ch1][0], ch1], [adj[ch1][0], ch1]]
		if len(c2) > 1:
			(ch1, ch2) = (c2[0], c2[1])
			for v in adj[ch1]:
				if v != ch2:
					sol = [[v, ch1], [v, ch2]]
					break
		for (i, j) in sol:
			print(i + 1, j + 1)

def iin():
	return int(input())

def lin():
	return list(map(int, input().split()))
main()