You are given an unweighted tree with $n$ vertices. Recall that a tree is a connected undirected graph without cycles.

Your task is to choose three distinct vertices $a, b, c$ on this tree such that the number of edges which belong to at least one of the simple paths between $a$ and $b$, $b$ and $c$, or $a$ and $c$ is the maximum possible. See the notes section for a better understanding.

The simple path is the path that visits each vertex at most once.


-----Input-----

The first line contains one integer number $n$ ($3 \le n \le 2 \cdot 10^5$) — the number of vertices in the tree. 

Next $n - 1$ lines describe the edges of the tree in form $a_i, b_i$ ($1 \le a_i$, $b_i \le n$, $a_i \ne b_i$). It is guaranteed that given graph is a tree.


-----Output-----

In the first line print one integer $res$ — the maximum number of edges which belong to at least one of the simple paths between $a$ and $b$, $b$ and $c$, or $a$ and $c$.

In the second line print three integers $a, b, c$ such that $1 \le a, b, c \le n$ and $a \ne, b \ne c, a \ne c$.

If there are several answers, you can print any.


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

Output
5
1 8 6



-----Note-----

The picture corresponding to the first example (and another one correct answer):

[Image]

If you choose vertices $1, 5, 6$ then the path between $1$ and $5$ consists of edges $(1, 2), (2, 3), (3, 4), (4, 5)$, the path between $1$ and $6$ consists of edges $(1, 2), (2, 3), (3, 4), (4, 6)$ and the path between $5$ and $6$ consists of edges $(4, 5), (4, 6)$. The union of these paths is $(1, 2), (2, 3), (3, 4), (4, 5), (4, 6)$ so the answer is $5$. It can be shown that there is no better answer.

Difficulty: EASY

Starter code:

Solutions:
import io
import os
from collections import Counter, defaultdict, deque
import heapq

def longestPathFrom(root, getNbr):
	queue = deque()
	queue.append(root)
	parent = {}
	parent[root] = None
	while queue:
		curr = queue.popleft()
		for child in getNbr(curr):
			if child not in parent:
				queue.append(child)
				parent[child] = curr
	ret = [curr]
	while curr in parent and parent[curr] is not None:
		curr = parent[curr]
		ret.append(curr)
	return ret[::-1]

def treeDiameter(graph):
	initNode = 0

	def getNbr(node):
		return graph[node]
	path1 = longestPathFrom(initNode, getNbr)
	assert path1[0] == initNode
	path2 = longestPathFrom(path1[-1], getNbr)
	return path2

def solve(N, edges):
	graph = [[] for i in range(N)]
	for (u, v) in edges:
		graph[u].append(v)
		graph[v].append(u)

	def getDeepest(u, exclude):
		retDepth = 0
		retChild = u
		for v in graph[u]:
			if v not in exclude:
				(childDepth, child) = getDeepest(v, [u])
				if 1 + childDepth > retDepth:
					retDepth = 1 + childDepth
					retChild = child
		return (retDepth, retChild)
	path = treeDiameter(graph)
	base = len(path) - 1
	best = (0, path[1])
	for i in range(1, len(path) - 1):
		best = max(best, getDeepest(path[i], [path[i - 1], path[i + 1]]))
	return str(base + best[0]) + '\n' + ' '.join((str(x + 1) for x in [path[0], best[1], path[-1]]))
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
(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)


class SegTree:

	def __init__(self, init_val, ide_ele, segfunc):
		self.n = len(init_val)
		self.num = 2 ** (self.n - 1).bit_length()
		self.ide_ele = ide_ele
		self.segfunc = segfunc
		self.seg = [ide_ele] * 2 * self.num
		for i in range(self.n):
			self.seg[i + self.num] = init_val[i]
		for i in range(self.num - 1, 0, -1):
			self.seg[i] = self.segfunc(self.seg[2 * i], self.seg[2 * i + 1])

	def update(self, k, x):
		k += self.num
		self.seg[k] = x
		while k:
			k = k >> 1
			self.seg[k] = self.segfunc(self.seg[2 * k], self.seg[2 * k + 1])

	def query(self, l, r):
		if r <= l:
			return self.ide_ele
		l += self.num
		r += self.num
		res = self.ide_ele
		while l < r:
			if r & 1:
				r -= 1
				res = self.segfunc(res, self.seg[r])
			if l & 1:
				res = self.segfunc(res, self.seg[l])
				l += 1
			l = l >> 1
			r = r >> 1
		return res

def segfunc(x, y):
	if x <= y:
		return x
	else:
		return y
ide_ele = 10 ** 18

class LCA:

	def __init__(self, g, root):
		self.n = len(g)
		self.root = root
		s = [self.root]
		self.parent = [-1] * self.n
		self.child = [[] for _ in range(self.n)]
		visit = [-1] * self.n
		visit[self.root] = 0
		while s:
			v = s.pop()
			for u in g[v]:
				if visit[u] == -1:
					self.parent[u] = v
					self.child[v].append(u)
					visit[u] = 0
					s.append(u)
		tank = [self.root]
		self.eulerTour = []
		self.left = [0] * self.n
		self.right = [-1] * self.n
		self.depth = [-1] * self.n
		eulerNum = -1
		de = -1
		while tank:
			v = tank.pop()
			if v >= 0:
				eulerNum += 1
				self.eulerTour.append(v)
				self.left[v] = eulerNum
				self.right[v] = eulerNum
				tank.append(~v)
				de += 1
				self.depth[v] = de
				for u in self.child[v]:
					tank.append(u)
			else:
				de -= 1
				if ~v != self.root:
					self.eulerTour.append(self.parent[~v])
					eulerNum += 1
					self.right[self.parent[~v]] = eulerNum
		A = [0] * (2 * self.n - 1)
		for (i, e) in enumerate(self.eulerTour):
			A[i] = self.depth[e] * (2 * self.n - 1) + i
		self.seg = SegTree(A, ide_ele, segfunc)

	def getLCA(self, u, v):
		p = min(self.left[u], self.left[v])
		q = max(self.right[u], self.left[v]) + 1
		m = self.seg.query(p, q)
		return self.eulerTour[m % (2 * self.n - 1)]
import sys
import io, os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
n = int(input())
g = [[] for i in range(n)]
for i in range(n - 1):
	(a, b) = map(int, input().split())
	(a, b) = (a - 1, b - 1)
	g[a].append(b)
	g[b].append(a)
INF = 10 ** 18
from collections import deque

def bfs(s, g):
	n = len(g)
	d = [INF] * n
	d[s] = 0
	q = deque([])
	q.append(s)
	while q:
		v = q.popleft()
		for u in g[v]:
			if d[u] == INF:
				d[u] = d[v] + 1
				q.append(u)
	return d
D1 = bfs(0, g)
M = max(D1)
for i in range(n):
	if D1[i] == M:
		x = i
		break
D2 = bfs(x, g)
M = max(D2)
for i in range(n):
	if D2[i] == M:
		y = i
		break
lca = LCA(g, 0)

def dist(u, v):
	l = lca.getLCA(u, v)
	d = lca.depth[u] + lca.depth[v] - 2 * lca.depth[l]
	return d
d0 = dist(x, y)
res = 0
ans = []
for i in range(n):
	if i == x or i == y:
		continue
	d1 = dist(x, i)
	d2 = dist(y, i)
	temp = (d0 + d1 + d2) // 2
	if temp > res:
		res = temp
		ans = [x + 1, y + 1, i + 1]
print(res)
print(*ans)


from collections import deque
from sys import stdin, stdout
n = int(input())
v = [[] for i in range(n + 1)]
d = deque()
(out, check) = ([0] * 3, [0] * (n + 1))
for i in range(n - 1):
	(a, b) = map(int, stdin.readline().split())
	v[a].append(b)
	v[b].append(a)

def dfs(k):
	global max, dad
	depth = [-1] * (n + 1)
	(ans1, max, dad) = (0, 0, [0] * (n + 1))
	d.append(k)
	depth[k] = 0
	while len(d) > 0:
		for i in range(len(v[d[0]])):
			if depth[v[d[0]][i]] == -1:
				depth[v[d[0]][i]] = depth[d[0]] + 1
				if check[v[d[0]][i]] == 1:
					depth[v[d[0]][i]] = 0
				dad[v[d[0]][i]] = d[0]
				if max < depth[v[d[0]][i]]:
					max = depth[v[d[0]][i]]
					ans1 = v[d[0]][i]
				d.append(v[d[0]][i])
		d.popleft()
	return ans1
out[0] = dfs(a)
out[1] = dfs(out[0])
ans = max
next = out[1]
for i in range(ans + 1):
	check[next] = 1
	next = dad[next]
out[2] = dfs(out[0])
if out[2] == 0:
	out[2] = dad[out[1]]
ans += max
stdout.write(str(ans))
stdout.write('\n')
stdout.write(str(out[0]))
stdout.write(' ')
stdout.write(str(out[1]))
stdout.write(' ')
stdout.write(str(out[2]))


import queue
ans = lambda : list(map(int, input().split()))
n = ans()[0]
(g, d, frm) = ([[] for _ in range(n)], [0] * n, [0] * n)
for _ in range(n - 1):
	(u, v) = ans()
	g[u - 1].append(v - 1)
	g[v - 1].append(u - 1)

def bfs(s):
	que = queue.SimpleQueue()
	que.put(s)
	for i in range(n):
		(d[i], frm[i]) = (-1, -1)
	d[s] = 0
	vertex = s
	while not que.empty():
		u = que.get()
		for v in g[u]:
			if ~d[v]:
				continue
			d[v] = d[u] + 1
			frm[v] = u
			if d[v] > d[vertex]:
				vertex = v
			que.put(v)
	return vertex
u = bfs(0)
v = bfs(u)
u = bfs(v)
(mark, nodes) = ([False] * n, [])

def dfs(u, fa=-1):
	res = [0, u]
	for v in g[u]:
		if mark[v] or v == fa:
			continue
		(t, tt) = dfs(v, u)
		if t + 1 > res[0]:
			res = [t + 1, tt]
	return res
x = u
while ~x:
	mark[x] = True
	nodes.append(x)
	x = frm[x]
(mx, z) = (0, nodes[1])
for x in nodes:
	(t, tt) = dfs(x)
	if t > mx:
		(mx, z) = (t, tt)
print(d[u] + mx)
print(u + 1, v + 1, z + 1)


import os, sys
from io import BytesIO, IOBase

def main():
	n = int(input())
	path = [[] for _ in range(n)]
	for _ in range(n - 1):
		(a1, b1) = map(lambda xx: int(xx) - 1, input().split())
		path[a1].append(b1)
		path[b1].append(a1)
	(st, poi, visi, node, maxi, he) = ([0], [0] * n, [1] + [0] * (n - 1), -1, -1, 0)
	while len(st):
		(x, y) = (st[-1], path[st[-1]])
		if poi[x] != len(y) and visi[y[poi[x]]]:
			poi[x] += 1
		if poi[x] == len(y):
			st.pop()
			he -= 1
		else:
			he += 1
			i = y[poi[x]]
			if he > maxi:
				(node, maxi) = (i, he)
			st.append(i)
			poi[x] += 1
			visi[i] = 1
	(length, which) = ([0] * n, [i for i in range(n)])
	(st, poi, visi, node1, maxi, he) = ([node], [0] * n, [0] * n, -1, -1, 0)
	visi[node] = 1
	while len(st):
		(x, y) = (st[-1], path[st[-1]])
		if poi[x] != len(y) and visi[y[poi[x]]]:
			poi[x] += 1
		if poi[x] == len(y):
			st.pop()
			he -= 1
			if len(st):
				if length[st[-1]] < length[x] + 1:
					length[st[-1]] = length[x] + 1
					which[st[-1]] = which[x]
		else:
			he += 1
			i = y[poi[x]]
			if he > maxi:
				(node1, maxi) = (i, he)
			st.append(i)
			poi[x] += 1
			visi[i] = 1
	(st, poi, visi) = ([node], [0] * n, [0] * n)
	visi[node] = 1
	se = [0] * n
	while len(st):
		(x, y) = (st[-1], path[st[-1]])
		if poi[x] != len(y) and visi[y[poi[x]]]:
			poi[x] += 1
		if poi[x] == len(y):
			st.pop()
		else:
			i = y[poi[x]]
			st.append(i)
			if i == node1:
				for j in st:
					se[j] = 1
				break
			poi[x] += 1
			visi[i] = 1
	if node and node1:
		ind = 0
	elif node != 1 and node1 != 1:
		ind = 1
	else:
		ind = 2
	if maxi == n - 1:
		print(maxi)
		print(node + 1, node1 + 1, ind + 1)
		exit()
	ma = -1
	for i in range(n):
		if not se[i] and length[i] > ma:
			(ma, ind) = (length[i], which[i])
	print(maxi + ma + 1)
	print(node + 1, node1 + 1, ind + 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')
main()


import sys
from collections import deque
n = int(input())
adj = [[] for _ in range(n)]
for (u, v) in (map(int, l.split()) for l in sys.stdin):
	adj[u - 1].append(v - 1)
	adj[v - 1].append(u - 1)
inf = 10 ** 9

def rec(s):
	prev = [-1] * n
	prev[s] = inf
	dq = deque([s])
	last = s
	while dq:
		v = dq.popleft()
		last = v
		for dest in adj[v]:
			if prev[dest] > -1:
				continue
			prev[dest] = v
			dq.append(dest)
	return (last, prev)
(v1, _) = rec(0)
(v2, prev) = rec(v1)
v = prev[v2]
visited = [0] * n
visited[v] = visited[v1] = visited[v2] = 1
dia = 0
(max_e, max_e_i) = (0, v)
while v != inf:
	dia += 1
	if prev[v] != inf:
		visited[prev[v]] = 1
	stack = [(v, 0)]
	while stack:
		(cv, e) = stack.pop()
		if max_e < e:
			(max_e, max_e_i) = (e, cv)
		e += 1
		for dest in adj[cv]:
			if visited[dest]:
				continue
			visited[dest] = 1
			stack.append((dest, e))
	v = prev[v]
print(dia + max_e)
print(v1 + 1, v2 + 1, max_e_i + 1)


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():
	n = int(input())
	graph = defaultdict(list)
	for i in range(n - 1):
		(a, b) = map(int, input().split())
		graph[a - 1].append(b - 1)
		graph[b - 1].append(a - 1)
	node = [0]
	ma = [0]

	def dfs(v, p, dep):
		if dep > ma[0]:
			ma[0] = dep
			node[0] = v
		for i in graph[v]:
			if i != p:
				dfs(i, v, dep + 1)
	parent = [-1] * n

	def dfs1(v, p):
		parent[v] = p
		for i in graph[v]:
			if i != p:
				dfs1(i, v)
	dfs(0, -1, 0)
	fi = node[0]
	node = [0]
	ma = [0]
	dfs(fi, -1, 0)
	se = node[0]
	dfs1(fi, -1)
	k = se
	que = []
	que.append(k)
	while parent[k] != -1:
		k = parent[k]
		que.append(k)
	ans = len(que) - 1
	dist = [9999999] * n
	e = []
	heapq.heapify(e)
	for i in que:
		dist[i] = 0
		heapq.heappush(e, (0, i))
	while e:
		(length, v) = heapq.heappop(e)
		for x in graph[v]:
			if length + 1 < dist[x]:
				dist[x] = length + 1
				heapq.heappush(e, (1 + length, x))
	m = 0
	third = 0
	for i in range(n):
		if dist[i] >= m and i != fi and (i != se):
			m = dist[i]
			third = i
	ans += m
	print(ans)
	print(fi + 1, se + 1, third + 1)
t = threading.Thread(target=main)
t.start()
t.join()


import sys
input = sys.stdin.readline
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)

def dfs(t):
	L = [-1] * (n + 1)
	L[t] = 0
	Q = [t]
	while Q:
		x = Q.pop()
		for to in E[x]:
			if L[to] == -1:
				L[to] = L[x] + 1
				Q.append(to)
	return L.index(max(L))
A = dfs(1)
B = dfs(A)
DEPTH = [-1] * (n + 1)
DEPTH[1] = 0
from collections import deque
QUE = deque([1])
QUE2 = deque()
EULER = []
USED = [0] * (n + 1)
while QUE:
	x = QUE.pop()
	EULER.append((DEPTH[x], x))
	if USED[x] == 1:
		continue
	for to in E[x]:
		if USED[to] == 0:
			DEPTH[to] = DEPTH[x] + 1
			QUE2.append(to)
		else:
			QUE.append(to)
	QUE.extend(QUE2)
	QUE2 = deque()
	USED[x] = 1
MINP = [1 << 30] * (n + 1)
MAXP = [-1] * (n + 1)
for (ind, (depth, p)) in enumerate(EULER):
	MINP[p] = min(MINP[p], ind)
	MAXP[p] = max(MAXP[p], ind)
LEN = len(EULER)
seg_el = 1 << LEN.bit_length()
SEG = [(1 << 30, 0)] * (2 * seg_el)
for i in range(LEN):
	SEG[i + seg_el] = EULER[i]
for i in range(seg_el - 1, 0, -1):
	SEG[i] = min(SEG[i * 2], SEG[i * 2 + 1])

def update(n, x, seg_el):
	i = n + seg_el
	SEG[i] = x
	i >>= 1
	while i != 0:
		SEG[i] = min(SEG[i * 2], SEG[i * 2 + 1])
		i >>= 1

def getvalues(l, r):
	L = l + seg_el
	R = r + seg_el
	ANS = (1 << 30, 0)
	while L < R:
		if L & 1:
			ANS = min(ANS, SEG[L])
			L += 1
		if R & 1:
			R -= 1
			ANS = min(ANS, SEG[R])
		L >>= 1
		R >>= 1
	return ANS

def LCA(l, r):
	return getvalues(min(MINP[l], MINP[r]), max(MAXP[l], MAXP[r]) + 1)
A2 = DEPTH[A] * 2 + DEPTH[B] * 2 - LCA(A, B)[0] * 2
ANS = 0
for i in range(1, n + 1):
	if i == A or i == B:
		continue
	if ANS < A2 + DEPTH[i] * 2 - LCA(i, A)[0] * 2 - LCA(i, B)[0] * 2:
		ANS = A2 + DEPTH[i] * 2 - LCA(i, A)[0] * 2 - LCA(i, B)[0] * 2
		Aind = i
print(ANS // 2)
print(A, B, Aind)


from collections import deque
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():
	n = int(input())
	adj = [[] for _ in range(n + 1)]
	for _ in range(n - 1):
		(u, v) = readIntArr()
		adj[v].append(u)
		adj[u].append(v)
	leaves = []
	for node in range(1, n + 1):
		if len(adj[node]) == 1:
			leaves.append(node)
	if len(leaves) == 2:
		node1 = leaves[0]
		node2 = leaves[1]
		for node in range(1, node + 1):
			if node != node1 and node != node2:
				node3 = node
				break
		print(n - 1)
		print('{} {} {}'.format(node1, node2, node3))
		return None
	visited = [False for _ in range(n + 1)]
	visited[leaves[0]] = True
	dfs = [[leaves[0], 0]]
	farNode1 = None
	maxDepth = 0
	while dfs:
		(node, d) = dfs.pop()
		if d > maxDepth:
			maxDepth = d
			farNode1 = node
		for nex in adj[node]:
			if not visited[nex]:
				visited[nex] = True
				dfs.append([nex, d + 1])
	visited = [False for _ in range(n + 1)]
	visited[farNode1] = True
	dfs = [[farNode1, 0]]
	farNode2 = None
	maxDepth = 0
	while dfs:
		(node, d) = dfs.pop()
		if d > maxDepth:
			maxDepth = d
			farNode2 = node
		for nex in adj[node]:
			if not visited[nex]:
				visited[nex] = True
				dfs.append([nex, d + 1])
	dist1_2 = maxDepth

	@bootstrap
	def dfs(node):
		if node == farNode2:
			yield True
		for nex in adj[node]:
			if len(path1_2Nodes) < 2 or path1_2Nodes[-2] != nex:
				path1_2Nodes.append(nex)
				if (yield dfs(nex)):
					yield True
				path1_2Nodes.pop()
		yield False
	path1_2Nodes = [farNode1]
	dfs(farNode1)
	q = deque()
	distFromPath = [-inf for _ in range(n + 1)]
	for node in path1_2Nodes:
		q.append([node, 0])
		distFromPath[node] = 0
	while q:
		(node, d) = q.popleft()
		for nex in adj[node]:
			if distFromPath[nex] == -inf:
				distFromPath[nex] = d + 1
				q.append([nex, d + 1])
	maxDistFromPath = -1
	farNode3 = 0
	for node in range(1, n + 1):
		if distFromPath[node] > maxDistFromPath:
			maxDistFromPath = distFromPath[node]
			farNode3 = node
	print(maxDistFromPath + dist1_2)
	print('{} {} {}'.format(farNode1, farNode2, farNode3))
	return
import sys
input = sys.stdin.buffer.readline

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]

def makeArr(*args):
	assert len(args) >= 2, 'makeArr args should be (default value, dimension 1, dimension 2,...'
	if len(args) == 2:
		return [args[0] for _ in range(args[1])]
	else:
		return [makeArr(args[0], *args[2:]) for _ in range(args[1])]

def queryInteractive(x, y):
	print('? {} {}'.format(x, y))
	sys.stdout.flush()
	return int(input())

def answerInteractive(ans):
	print('! {}'.format(ans))
	sys.stdout.flush()
inf = float('inf')
MOD = 10 ** 9 + 7
for _abc in range(1):
	main()


import sys, math, itertools
from collections import Counter, deque, defaultdict
from bisect import bisect_left, bisect_right
from heapq import heappop, heappush, heapify, nlargest
from copy import deepcopy
mod = 10 ** 9 + 7
INF = float('inf')

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

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

def inpl_1():
	return list(map(lambda x: int(x) - 1, sys.stdin.readline().split()))

def inps():
	return sys.stdin.readline()

def inpsl(x):
	tmp = sys.stdin.readline()
	return list(tmp[:x])

def err(x):
	print(x)
	exit()
LV = 21

def construct(prv):
	kprv = [prv]
	S = prv
	for k in range(20):
		T = [-1] * n
		for i in range(n):
			if S[i] == -1:
				continue
			T[i] = S[S[i]]
		kprv.append(T)
		S = T
	return kprv

def lca(u, v, kprv, depth):
	dd = depth[v] - depth[u]
	if dd < 0:
		(u, v) = (v, u)
		dd = -dd
	for k in range(LV + 1):
		if dd & 1:
			v = kprv[k][v]
		dd >>= 1
	if u == v:
		return u
	for k in range(LV - 1, -1, -1):
		pu = kprv[k][u]
		pv = kprv[k][v]
		if pu != pv:
			u = pu
			v = pv
	return kprv[0][u]
n = inp()
ab = [inpl_1() for _ in range(n - 1)]
g = [[] for _ in range(n)]
for (a, b) in ab:
	g[a].append(b)
	g[b].append(a)
pa = [-1] * n

def bfs(s):
	q = deque([s])
	depth = [-1] * n
	depth[s] = 0
	while q:
		v = q.popleft()
		for u in g[v]:
			if depth[u] == -1:
				depth[u] = depth[v] + 1
				pa[u] = v
				q.append(u)
	return depth
depth = bfs(0)
mx = -1
root = -1
for (i, x) in enumerate(depth):
	if x > mx:
		mx = x
		root = i
depth = bfs(root)
mx = -1
B = -1
for (i, x) in enumerate(depth):
	if x > mx:
		mx = x
		B = i
res = -1
C = -1
kprv = construct(pa)
for i in range(n):
	if i == B or i == root:
		continue
	l = lca(i, B, kprv, depth)
	ans = depth[i] - depth[l]
	if ans > res:
		C = i
		res = ans
print(res + mx)
print(root + 1, B + 1, C + 1)


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

def longestPathFrom(root, getNbr):
	queue = deque()
	queue.append(root)
	parent = {}
	parent[root] = None
	while queue:
		curr = queue.popleft()
		for child in getNbr(curr):
			if child not in parent:
				queue.append(child)
				parent[child] = curr
	ret = [curr]
	while curr in parent and parent[curr] is not None:
		curr = parent[curr]
		ret.append(curr)
	return ret[::-1]

def treeDiameter(graph):
	initNode = 0

	def getNbr(node):
		return graph[node]
	path1 = longestPathFrom(initNode, getNbr)
	assert path1[0] == initNode
	path2 = longestPathFrom(path1[-1], getNbr)
	return path2

def solve(N, edges):
	graph = [[] for i in range(N)]
	for (u, v) in edges:
		graph[u].append(v)
		graph[v].append(u)
	path = treeDiameter(graph)
	pathSet = set(path)

	def getNonDiameterNbr(node):
		for nbr in graph[node]:
			if nbr not in pathSet:
				yield nbr
	base = len(path) - 1
	best = (0, path[1])
	for i in range(1, len(path) - 1):
		deepest = longestPathFrom(path[i], getNonDiameterNbr)
		assert deepest[0] == path[i]
		best = max(best, (len(deepest) - 1, deepest[-1]))
	return str(base + best[0]) + '\n' + ' '.join((str(x + 1) for x in [path[0], best[1], path[-1]]))
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
(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 defaultdict, deque
import sys
import io, os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

def bfs(root, path):
	depth = [0] * (n + 1)
	parent = [0] * (n + 1)
	parent[root] = -1
	queue = deque([root])
	visited = set()
	visited.add(root)
	while queue:
		vertex = queue.popleft()
		for child in graph[vertex]:
			if child not in visited:
				if child in path:
					depth[child] = 0
				else:
					depth[child] = depth[vertex] + 1
				parent[child] = vertex
				visited.add(child)
				queue.append(child)
	(onee, dist) = (1, 0)
	if len(path) > 0:
		if one != 1 and two != 1:
			onee = 1
		elif one != 2 and two != 2:
			onee = 2
		else:
			onee = 3
	for i in range(1, n + 1):
		if depth[i] > dist:
			onee = i
			dist = depth[i]
	return (onee, dist, parent)

def restore(a, s):
	res = set()
	while s != -1:
		res.add(s)
		s = a[s]
	return res
graph = defaultdict(list)
n = int(input())
for i in range(n - 1):
	(a, b) = map(int, input().split())
	graph[a].append(b)
	graph[b].append(a)
(one, dist, par) = bfs(1, set())
(two, dist, par) = bfs(one, set())
ans = dist
path = restore(par, two)
(three, dist, par) = bfs(one, path)
print(ans + dist)
print(one, two, three)


class HLD:

	def __init__(self, g):
		self.g = g
		self.n = len(g)
		self.parent = [-1] * self.n
		self.size = [1] * self.n
		self.head = [0] * self.n
		self.preorder = [0] * self.n
		self.k = 0
		self.depth = [0] * self.n
		for v in range(self.n):
			if self.parent[v] == -1:
				self.dfs_pre(v)
				self.dfs_hld(v)

	def dfs_pre(self, v):
		g = self.g
		stack = [v]
		order = [v]
		while stack:
			v = stack.pop()
			for u in g[v]:
				if self.parent[v] == u:
					continue
				self.parent[u] = v
				self.depth[u] = self.depth[v] + 1
				stack.append(u)
				order.append(u)
		while order:
			v = order.pop()
			child_v = g[v]
			if len(child_v) and child_v[0] == self.parent[v]:
				(child_v[0], child_v[-1]) = (child_v[-1], child_v[0])
			for (i, u) in enumerate(child_v):
				if u == self.parent[v]:
					continue
				self.size[v] += self.size[u]
				if self.size[u] > self.size[child_v[0]]:
					(child_v[i], child_v[0]) = (child_v[0], child_v[i])

	def dfs_hld(self, v):
		stack = [v]
		while stack:
			v = stack.pop()
			self.preorder[v] = self.k
			self.k += 1
			top = self.g[v][0]
			for u in reversed(self.g[v]):
				if u == self.parent[v]:
					continue
				if u == top:
					self.head[u] = self.head[v]
				else:
					self.head[u] = u
				stack.append(u)

	def for_each(self, u, v):
		while True:
			if self.preorder[u] > self.preorder[v]:
				(u, v) = (v, u)
			l = max(self.preorder[self.head[v]], self.preorder[u])
			r = self.preorder[v]
			yield (l, r)
			if self.head[u] != self.head[v]:
				v = self.parent[self.head[v]]
			else:
				return

	def for_each_edge(self, u, v):
		while True:
			if self.preorder[u] > self.preorder[v]:
				(u, v) = (v, u)
			if self.head[u] != self.head[v]:
				yield (self.preorder[self.head[v]], self.preorder[v])
				v = self.parent[self.head[v]]
			else:
				if u != v:
					yield (self.preorder[u] + 1, self.preorder[v])
				break

	def subtree(self, v):
		l = self.preorder[v]
		r = self.preorder[v] + self.size[v]
		return (l, r)

	def lca(self, u, v):
		while True:
			if self.preorder[u] > self.preorder[v]:
				(u, v) = (v, u)
			if self.head[u] == self.head[v]:
				return u
			v = self.parent[self.head[v]]
import sys
import io, os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
n = int(input())
g = [[] for i in range(n)]
for i in range(n - 1):
	(a, b) = map(int, input().split())
	(a, b) = (a - 1, b - 1)
	g[a].append(b)
	g[b].append(a)
INF = 10 ** 18
from collections import deque

def bfs(s, g):
	n = len(g)
	d = [INF] * n
	d[s] = 0
	q = deque([])
	q.append(s)
	while q:
		v = q.popleft()
		for u in g[v]:
			if d[u] == INF:
				d[u] = d[v] + 1
				q.append(u)
	return d
D1 = bfs(0, g)
M = max(D1)
for i in range(n):
	if D1[i] == M:
		x = i
		break
D2 = bfs(x, g)
M = max(D2)
for i in range(n):
	if D2[i] == M:
		y = i
		break
hld = HLD(g)

def dist(u, v):
	l = hld.lca(u, v)
	d = hld.depth[u] + hld.depth[v] - 2 * hld.depth[l]
	return d
d0 = dist(x, y)
res = 0
ans = []
for i in range(n):
	if i == x or i == y:
		continue
	d1 = dist(x, i)
	d2 = dist(y, i)
	temp = (d0 + d1 + d2) // 2
	if temp > res:
		res = temp
		ans = [x + 1, y + 1, i + 1]
print(res)
print(*ans)


from sys import stdin, stdout
from collections import namedtuple
import sys, threading
n = 0
graph = []
names = ['count', 'elements']
stack = []
current_max = []

def dp(current, previous):
	global graph
	global names
	global stack
	global current_max
	current_max = [0] * (n + 1)
	stack.append(current)
	max = [{k: v for (k, v) in zip(names, [0, set()])} for i in range(3)]
	while stack:
		if current_max[current] == 0:
			current_max[current] = [[{k: v for (k, v) in zip(names, [0, set()])} for _ in range(3 - i)] for i in range(3)]
		for i in range(3):
			for j in range(3 - i):
				if max[i]['count'] > current_max[current][i][j]['count']:
					for k in range(3 - i - 1, j, -1):
						current_max[current][i][k]['count'] = current_max[current][i][k - 1]['count']
						current_max[current][i][k]['elements'] = current_max[current][i][k - 1]['elements']
					current_max[current][i][j]['count'] = max[i]['count']
					current_max[current][i][j]['elements'] = max[i]['elements']
					break
		while graph[current]:
			if previous in graph[current]:
				graph[current].discard(previous)
				continue
			x = graph[current].pop()
			stack.append(x)
			graph[current].discard(x)
			previous = current
			current = x
		if current_max[current] == 0:
			current_max[current] = [[{k: v for (k, v) in zip(names, [0, set()])} for _ in range(3 - i)] for i in range(3)]
		if current_max[current][0][0]['count'] + current_max[current][0][1]['count'] + current_max[current][0][2]['count'] > current_max[current][2][0]['count'] and current_max[current][0][2]['count'] and current_max[current][0][1]['count'] and current_max[current][0][0]['count']:
			current_max[current][2][0]['count'] = current_max[current][0][0]['count'] + current_max[current][0][1]['count'] + current_max[current][0][2]['count']
			current_max[current][2][0]['elements'] = current_max[current][0][0]['elements'].union(current_max[current][0][1]['elements'], current_max[current][0][2]['elements'])
		if current_max[current][1][0]['count'] and current_max[current][0][0]['count'] and current_max[current][0][0]['elements'].difference(current_max[current][1][0]['elements']):
			if current_max[current][0][0]['count'] + current_max[current][1][0]['count'] > current_max[current][2][0]['count']:
				current_max[current][2][0]['count'] = current_max[current][0][0]['count'] + current_max[current][1][0]['count']
				current_max[current][2][0]['elements'] = current_max[current][0][0]['elements'].union(current_max[current][1][0]['elements'])
		if current_max[current][1][0]['count'] and current_max[current][0][1]['count'] and (current_max[current][0][1]['count'] + current_max[current][1][0]['count'] > current_max[current][2][0]['count']) and current_max[current][0][1]['elements'].difference(current_max[current][1][0]['elements']):
			current_max[current][2][0]['count'] = current_max[current][0][1]['count'] + current_max[current][1][0]['count']
			current_max[current][2][0]['elements'] = current_max[current][0][1]['elements'].union(current_max[current][1][0]['elements'])
		if current_max[current][0][0]['count'] and current_max[current][1][1]['count'] and (current_max[current][0][0]['count'] + current_max[current][1][1]['count'] > current_max[current][2][0]['count']) and current_max[current][0][0]['elements'].difference(current_max[current][1][1]['elements']):
			current_max[current][2][0]['count'] = current_max[current][0][0]['count'] + current_max[current][1][1]['count']
			current_max[current][2][0]['elements'] = current_max[current][0][0]['elements'].union(current_max[current][1][1]['elements'])
		if current_max[current][0][0]['count'] and current_max[current][0][1]['count'] and (current_max[current][0][0]['count'] + current_max[current][0][1]['count'] > current_max[current][1][0]['count']):
			current_max[current][1][0]['count'] = current_max[current][0][0]['count'] + current_max[current][0][1]['count']
			current_max[current][1][0]['elements'] = current_max[current][0][0]['elements'].union(current_max[current][0][1]['elements'])
		current_max[current][0][0]['count'] += 1
		if not current_max[current][0][0]['elements']:
			current_max[current][0][0]['elements'].add(current)
		if current_max[current][1][0]['count']:
			current_max[current][1][0]['count'] += 1
		max = [current_max[current][0][0], current_max[current][1][0], current_max[current][2][0]]
		stack.pop()
		current_max[current].clear()
		if stack:
			current = stack[-1]
	return max

def main():
	global graph
	global n
	n = int(stdin.readline())
	graph = [set() for _ in range(n + 1)]
	for _ in range(n - 1):
		(x, y) = list(map(int, stdin.readline().split()))
		graph[x].add(y)
		graph[y].add(x)
	ans = dp(1, -1)
	if ans[0]['count'] - 1 > ans[1]['count'] - 1 and ans[0]['count'] - 1 > ans[2]['count']:
		ans[0]['elements'].add(1)
		ans[0]['elements'].add(2)
		if len(ans[0]['elements']) == 2:
			ans[0]['elements'].add(3)
		stdout.write(str(ans[0]['count'] - 1) + '\n' + ' '.join((str(s) for s in ans[0]['elements'])))
	elif ans[1]['count'] - 1 > ans[2]['count']:
		ans[1]['elements'].add(1)
		stdout.write(str(ans[1]['count'] - 1) + '\n' + ' '.join((str(s) for s in ans[1]['elements'])))
	else:
		stdout.write(str(ans[2]['count']) + '\n' + ' '.join((str(s) for s in ans[2]['elements'])))
thread = threading.Thread(target=main)
thread.start()


from collections import deque
import sys
ans = 0
input = sys.stdin.readline
n = int(input())

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

def bfs(l):
	dis = [0] * n
	for i in l:
		dis[i] = 1
		q.append(i)
	i = -1
	while q:
		i = q.popleft()
		for j in tree[i]:
			if dis[j] == 0:
				parent[j] = i
				q.append(j)
				dis[j] = dis[i] + 1
	return (i, dis[i])
parent = [-1] * n
tree = [[] for _ in range(n)]
for _ in range(n - 1):
	(x, y) = put()
	tree[x - 1].append(y - 1)
	tree[y - 1].append(x - 1)
q = deque()
(far, _) = bfs([0])
(end, dis) = bfs([far])
parent[far] = -1
curr = end
l = []
while curr != -1:
	l.append(curr)
	curr = parent[curr]
(third, dis2) = bfs(l)
if third in [far, end]:
	x = 0
	while x in [far, end]:
		x += 1
	third = x
print(dis + dis2 - 2)
print(far + 1, end + 1, third + 1)


import sys
input = sys.stdin.readline
import math
import copy
import collections
from collections import deque

def bfs(vert):
	global adj, visited
	q = deque()
	q.append([vert, 0])
	while q:
		(temp, dist) = q.popleft()
		visited.add(temp)
		for edge in adj[temp]:
			if edge not in visited:
				q.append([edge, dist + 1])
		if not q:
			return [temp, dist]

def findpath(a, b):
	global path, adj, visited
	q = deque()
	q.append(a)
	firsts = []
	while q:
		temp = q.pop()
		path.append(temp)
		visited.add(temp)
		if temp == b:
			return
		leaf = True
		first = -1
		for edge in adj[temp]:
			if edge not in visited:
				if leaf:
					first = edge
				leaf = False
				q.append(edge)
		if first != -1:
			firsts.append(first)
		if leaf:
			remove = path.pop()
			while remove == firsts[-1]:
				firsts.pop()
				remove = path.pop()

def bfs2(path):
	global visited
	c = -1
	farthest = -1
	for node in path[1:len(path) - 1]:
		(temp, dist) = bfs(node)
		if dist > farthest:
			farthest = dist
			c = temp
	return [c, farthest]
n = int(input())
adj = dict()
for i in range(n - 1):
	(u, v) = map(int, input().split())
	if u not in adj:
		adj[u] = set()
	if v not in adj:
		adj[v] = set()
	adj[v].add(u)
	adj[u].add(v)
visited = set()
(a, _) = bfs(1)
visited = set()
(b, _) = bfs(a)
path = []
visited = set()
findpath(a, b)
visited = set(path)
(c, dist) = bfs2(path)
print(len(path) - 1 + dist)
print(a, b, c)


import sys
from collections import defaultdict

def diam(graph):
	n = len(graph)
	(st, m) = (0, -1)
	mark = [0] * n
	dist = [0] * n
	dist2 = [0] * n
	ret = [0] * 4
	q = []
	for i in range(1, 4):
		q.append(st)
		mark = [0] * n
		mark[st] = 1
		dist[st] = 0
		far = st
		while q:
			u = q.pop()
			if i > 1:
				dist2[u] += dist[u]
			if dist[u] > dist[far]:
				far = u
			for v in graph[u]:
				if mark[v]:
					continue
				mark[v] = 1
				dist[v] = 1 + dist[u]
				q.append(v)
		ret[i] = far + 1
		ret[0] = dist[far]
		st = far
	for i in range(n):
		if i + 1 == ret[2] or i + 1 == ret[3]:
			continue
		if m == -1 or dist2[i] > dist2[m]:
			m = i
	ret[1] = m + 1
	ret[0] += (dist2[m] - ret[0]) // 2
	return ret
graph = defaultdict(list)
n = int(sys.stdin.readline())
for i in range(n - 1):
	(u, v) = map(int, sys.stdin.readline().split())
	u -= 1
	v -= 1
	graph[u].append(v)
	graph[v].append(u)
ans = diam(graph)
print(ans[0])
print(*ans[1:])


from collections import namedtuple, deque
from sys import stdin

def load_graph():
	n = int(stdin.readline())
	G = [set() for i in range(n)]
	for line in stdin.readlines():
		(a, b) = line.split()
		(a, b) = (int(a) - 1, int(b) - 1)
		G[a].add(b)
		G[b].add(a)
	return G

def find_all_distances(G, node):
	distances = [None for i in range(len(G))]
	distances[node] = 0
	queue = deque((node,))
	while len(queue) > 0:
		current_node = queue.popleft()
		for neighbor in G[current_node]:
			if distances[neighbor] is None:
				distances[neighbor] = distances[current_node] + 1
				queue.append(neighbor)
	return distances

def find_maxdist_triplet(G):
	distances_0 = find_all_distances(G, 0)
	(node_a, a_0_dist) = max(enumerate(distances_0), key=lambda d: d[1])
	distances_a = find_all_distances(G, node_a)
	(node_b, a_b_dist) = max(enumerate(distances_a), key=lambda d: d[1])
	distances_b = find_all_distances(G, node_b)
	distances_sum = [dist_a + dist_b for (dist_a, dist_b) in zip(distances_a, distances_b)]
	(node_c, c_ab_dist) = max(((node, distance) for (node, distance) in enumerate(distances_sum) if node != node_a and node != node_b), key=lambda d: d[1])
	abc_dist = a_b_dist + c_ab_dist
	return (abc_dist, node_a, node_b, node_c)
G = load_graph()
(dist_sum, path_a, path_b, path_c) = find_maxdist_triplet(G)
print(dist_sum // 2)
print(path_a + 1, path_b + 1, path_c + 1)


import sys
input = sys.stdin.readline
NEGINF = -1000000
n = int(input())
adj = [[] for i in range(n)]
parent = [-1] * n
visited = [False] * n
for _ in range(n - 1):
	(a, b) = map(int, input().split())
	adj[a - 1].append(b - 1)
	adj[b - 1].append(a - 1)
tup = tuple()
outs = [tup] * n
q = [(0, 0)]
while q:
	(node, type) = q.pop()
	if type == 0:
		visited[node] = True
		q.append((node, 1))
		for v in adj[node]:
			if not visited[v]:
				parent[v] = node
				q.append((v, 0))
	else:
		ones = [(0, node)]
		twos = []
		threes = []
		for v in adj[node]:
			if v != parent[node]:
				(a, b, c) = outs[v]
				ones.append((a[0] + 1, a[1], v))
				twos.append((b[0] + 1, b[1], v))
				threes.append(c)
		ones.sort(reverse=True)
		twos.sort(reverse=True)
		threes.sort(reverse=True)
		bestOne = (ones[0][0], ones[0][1])
		bestsTwo = [(NEGINF, (0, 0))]
		if len(twos) > 0:
			bestsTwo.append((twos[0][0], twos[0][1]))
		if len(ones) > 1:
			o1 = ones[0]
			o2 = ones[1]
			bestsTwo.append((o1[0] + o2[0], (o1[1], o2[1])))
		bestsThree = [(NEGINF, (0, 0, 0))]
		if len(threes) > 0:
			bestsThree.append(threes[0])
		if len(ones) > 2:
			o1 = ones[0]
			o2 = ones[1]
			o3 = ones[2]
			bestsThree.append((o1[0] + o2[0] + o3[0], (o1[1], o2[1], o3[1])))
		if len(twos) > 0:
			o1 = ones[0]
			t1 = twos[0]
			if o1[2] != t1[2]:
				bestsThree.append((o1[0] + t1[0], (o1[1], t1[1][0], t1[1][1])))
			else:
				if len(twos) > 1:
					t2 = twos[1]
					bestsThree.append((o1[0] + t2[0], (o1[1], t2[1][0], t2[1][1])))
				if len(ones) > 1:
					o2 = ones[1]
					bestsThree.append((o2[0] + t1[0], (o2[1], t1[1][0], t1[1][1])))
		outs[node] = (bestOne, max(bestsTwo), max(bestsThree))
final = outs[0][2]
print(final[0])
print(' '.join(map(lambda x: str(x + 1), final[1])))


from sys import stdin
from _collections import deque
mod = 10 ** 9 + 7
import sys
sys.setrecursionlimit(10 ** 5)
from queue import PriorityQueue
from bisect import bisect_right
from bisect import bisect_left
from collections import defaultdict
from math import sqrt, factorial, gcd, log2, inf, ceil
import heapq
input = lambda : sys.stdin.readline().rstrip()
from sys import stdin, stdout
from heapq import heapify, heappush, heappop
import sys
from collections import defaultdict

def diam(graph):
	n = len(graph)
	(st, m) = (0, -1)
	mark = [0] * n
	dist = [0] * n
	dist2 = [0] * n
	ret = [0] * 4
	q = []
	for i in range(1, 4):
		q.append(st)
		mark = [0] * n
		mark[st] = 1
		dist[st] = 0
		far = st
		while q:
			u = q.pop()
			if i > 1:
				dist2[u] += dist[u]
			if dist[u] > dist[far]:
				far = u
			for v in graph[u]:
				if mark[v]:
					continue
				mark[v] = 1
				dist[v] = 1 + dist[u]
				q.append(v)
		ret[i] = far + 1
		ret[0] = dist[far]
		st = far
	for i in range(n):
		if i + 1 == ret[2] or i + 1 == ret[3]:
			continue
		if m == -1 or dist2[i] > dist2[m]:
			m = i
	ret[1] = m + 1
	ret[0] += (dist2[m] - ret[0]) // 2
	return ret
graph = defaultdict(list)
n = int(sys.stdin.readline())
for i in range(n - 1):
	(u, v) = map(int, sys.stdin.readline().split())
	u -= 1
	v -= 1
	graph[u].append(v)
	graph[v].append(u)
ans = diam(graph)
print(ans[0])
print(*ans[1:])


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 factorial
from collections import Counter, defaultdict, deque
from heapq import heapify, heappop, heappush

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 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 ctd(chr):
	return ord(chr) - ord('a')
mod = 998244353
INF = float('inf')

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

	def BFS(nd):
		nonlocal par
		q = deque()
		q.append((nd, 0))
		vis = [0] * (n + 1)
		vis[nd] = 1
		lst = (-1, 0)
		while q:
			(nd, d) = q.popleft()
			lst = (nd, d)
			for nex in gp[nd]:
				if vis[nex] == 1:
					continue
				vis[nex] = 1
				q.append((nex, d + 1))
				par[nex] = nd
		return lst
	(a, _) = BFS(1)
	par = [-1] * (n + 1)
	(b, l) = BFS(a)
	c = (-1, 0)
	q = deque()
	vis = [0] * (n + 1)
	nd = b
	while par[nd] != -1:
		q.append((nd, 0))
		vis[nd] = 1
		nd = par[nd]
	vis[nd] = 1
	while q:
		(nd, d) = q.popleft()
		c = (nd, d)
		for nex in gp[nd]:
			if vis[nex] == 1:
				continue
			vis[nex] = 1
			q.append((nex, d + 1))
	pc = c[0]
	if pc == -1:
		for i in range(1, n + 1):
			if i != a and i != b:
				pc = i
				break
	print(c[1] + l)
	print(a, b, pc)
main()


import sys

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

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

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

def solve():
	global ans
	n = mint()
	e = [[] for i in range(n)]
	D = [0] * n
	ans = 0
	ansv = [0, 0, 0]
	for i in range(n - 1):
		(a, b) = mints()
		e[a - 1].append(b - 1)
		e[b - 1].append(a - 1)
	s = [0] * n
	p = [0] * n
	i = [0] * n
	d = [0] * n
	t = 0
	d[0] = (0, 0)
	p[0] = -1
	while t >= 0:
		x = s[t]
		ii = i[t]
		if ii > 0:
			v = e[x][ii - 1]
			if v != p[t]:
				dd = D[v]
				d[t] = min(d[t], (dd[0] - 1, dd[1]))
		if ii < len(e[x]):
			v = e[x][ii]
			i[t] = ii + 1
			if v != p[t]:
				t += 1
				s[t] = v
				p[t] = x
				d[t] = (0, v)
				i[t] = 0
		else:
			D[x] = d[t]
			t -= 1
	up = [0] * n
	upv = [0] * n
	a = [None] * n
	t = 0
	s[0] = 0
	p[0] = 0
	i[0] = 0
	aa = []
	for vv in e[0]:
		aa.append((D[vv][0] - 1, D[vv][1]))
		if len(aa) > 3:
			aa.sort()
			aa.pop()
	aa.append((0, 0))
	if len(aa) > 3:
		aa.sort()
		aa.pop()
	h = 0
	for (dd, vv) in aa:
		h -= dd
	if len(aa) == 3 and ans < h:
		ans = h
		for z in (0, 1, 2):
			ansv[z] = aa[z][1]
	a[0] = aa
	while t >= 0:
		x = s[t]
		ii = i[t]
		if ii < len(e[x]):
			v = e[x][ii]
			i[t] = ii + 1
			if v != p[t]:
				t += 1
				s[t] = v
				p[t] = x
				i[t] = 0
				aa = []
				dd = (D[v][0] - 1, D[v][1])
				b = (1, -1)
				for z in a[t - 1]:
					if z != dd:
						b = min(b, z)
				if b[1] != v:
					aa.append((b[0] - 1, b[1]))
				for vv in e[v]:
					if vv != x:
						aa.append((D[vv][0] - 1, D[vv][1]))
						if len(aa) > 3:
							aa.sort()
							aa.pop()
				aa.append((0, v))
				if len(aa) > 3:
					aa.sort()
					aa.pop()
				h = 0
				for (dd, vv) in aa:
					h -= dd
				if len(aa) == 3 and ans < h:
					ans = h
					for z in (0, 1, 2):
						ansv[z] = aa[z][1]
				a[t] = aa
		else:
			t -= 1
	print(ans)
	print(ansv[0] + 1, ansv[1] + 1, ansv[2] + 1)
solve()


def dfs(n, source, neighbors):
	dist = [-1] * n
	parent = [-1] * n
	height = [-1] * n
	height_ptr = [-1] * n
	deepest = 0
	deepest_ptr = source
	dist[source] = 0
	parent[source] = source
	stack = [source]
	while stack:
		u = stack[-1]
		is_processed = True
		for v in neighbors[u]:
			if parent[v] == -1:
				is_processed = False
				dist[v] = dist[u] + 1
				if dist[v] > deepest:
					deepest = dist[v]
					deepest_ptr = v
				parent[v] = u
				stack.append(v)
		if is_processed:
			stack.pop()
			max_height = -1
			max_height_ptr = -1
			for v in neighbors[u]:
				if parent[v] == u:
					if height[v] > max_height:
						max_height = height[v]
						max_height_ptr = v
			height[u] = 1 + max_height
			height_ptr[u] = max_height_ptr
	return (dist, parent, deepest, deepest_ptr, height, height_ptr)

def find_diameter(n, r, neighbors):
	(_, _, _, v1, _, _) = dfs(n, r, neighbors)
	(_, parent, size, v2, height, height_ptr) = dfs(n, v1, neighbors)
	return (v1, v2, size, height, height_ptr, parent)
n = int(input())
neighbors = [[] for i in range(n)]
for i in range(n - 1):
	(a, b) = map(int, input().split())
	neighbors[a - 1].append(b - 1)
	neighbors[b - 1].append(a - 1)
(v1, v2, size, height, height_ptr, parent) = find_diameter(n, 0, neighbors)
walker_prev = -1
walker = v2
max_height = 0
max_height_ptr = -1
while walker != v1:
	for branch in neighbors[walker]:
		if parent[branch] == walker and branch != walker_prev:
			if height[branch] + 1 > max_height:
				max_height = height[branch] + 1
				max_height_ptr = branch
	walker_prev = walker
	walker = parent[walker]
if max_height_ptr == -1:
	print(size)
	print(v1 + 1, parent[v2] + 1, v2 + 1)
else:
	v3 = max_height_ptr
	while height_ptr[v3] != -1:
		v3 = height_ptr[v3]
	print(max_height + size)
	print(v1 + 1, v2 + 1, v3 + 1)


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

def bfs(s):
	q = deque()
	q.append(s)
	dist1 = [-1] * (n + 1)
	dist1[s] = 0
	while q:
		i = q.popleft()
		di = dist1[i]
		for j in G[i]:
			if dist1[j] == -1:
				dist1[j] = di + 1
				q.append(j)
	a = i
	q.append(i)
	dist2 = [-1] * (n + 1)
	dist2[i] = 0
	while q:
		i = q.popleft()
		di = dist2[i]
		for j in G[i]:
			if dist2[j] == -1:
				dist2[j] = di + 1
				q.append(j)
	b = i
	d = dist2[i]
	ans = d
	dist3 = [-1] * (n + 1)
	while d:
		dist3[i] = 0
		q.append(i)
		for j in G[i]:
			if dist2[j] == d - 1:
				d -= 1
				i = j
				break
	dist3[i] = 0
	q.append(i)
	while q:
		i = q.popleft()
		di = dist3[i]
		for j in G[i]:
			if dist3[j] == -1:
				dist3[j] = di + 1
				q.append(j)
	c = i
	ans += dist3[i]
	if a == c or b == c:
		for i in range(1, n + 1):
			if a ^ i and b ^ i:
				c = i
				break
	return (ans, a, b, c)
n = int(input())
G = [[] for _ in range(n + 1)]
for _ in range(n - 1):
	(a, b) = map(int, input().split())
	G[a].append(b)
	G[b].append(a)
(ans, a, b, c) = bfs(1)
print(ans)
print(a, b, c)


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
from collections import deque
import random
input = sys.stdin.readline
n = int(input().strip())
tree = [[] for i in range(n + 1)]
for i in range(n - 1):
	(a, b) = map(int, input().strip().split())
	tree[a].append(b)
	tree[b].append(a)
q = deque()
root = random.randrange(1, n + 1)
max_dep = 0
max_node = root
for node in tree[root]:
	q.append((node, root, 1))
while len(q) > 0:
	(node, pd, dep) = q.popleft()
	if len(tree[node]) <= 1:
		if dep > max_dep:
			max_node = node
			max_dep = dep
	for child in tree[node]:
		if child == pd:
			continue
		q.append((child, node, dep + 1))
pa = [0 for i in range(n + 1)]
pa[root] = root
root = max_node
se = 0
max_dep = 0
first = max_node
for node in tree[root]:
	q.append((node, root, 1))
while len(q) > 0:
	(node, pd, dep) = q.popleft()
	pa[node] = pd
	if len(tree[node]) <= 1:
		if dep > max_dep:
			se = node
			max_dep = dep
	for child in tree[node]:
		if child == pd:
			continue
		q.append((child, node, dep + 1))
ans = max_dep
max_dep = [0]
max_node = [se]

@bootstrap
def dfs(node, pd, depth, desc):
	if len(tree[node]) <= 1:
		if depth > max_dep[0]:
			max_dep[0] = depth
			max_node[0] = node
		yield max_dep
	for child in tree[node]:
		if child == pd or child == desc:
			continue
		yield dfs(child, node, depth + 1, desc)
	yield max_dep
to_dfs = pa[se]
desc = se
while pa[to_dfs] != to_dfs:
	dfs(to_dfs, pa[to_dfs], 0, desc)
	desc = to_dfs
	to_dfs = pa[to_dfs]
third = max_node[0]
print(ans + max_dep[0])
if third == se:
	print(first, se, pa[se])
else:
	print(first, se, third)


from sys import stdin
from sys import exc_info

def input():
	return next(stdin)

def main():
	n = int(input())
	g = [set() for _ in range(n)]
	p = [0] * n
	for _ in range(n - 1):
		(l, r) = map(int, input().split())
		l -= 1
		r -= 1
		g[l].add(r)
		g[r].add(l)

	def dfs(v):
		d = [(1, i) for i in range(n)]
		q = [v]
		p[v] = None
		for w in q:
			for x in g[w]:
				if x != p[w]:
					p[x] = w
					q.append(x)
		for w in q[:0:-1]:
			d[p[w]] = max(d[p[w]], (d[w][0] + 1, d[w][1]))
		return d
	da = dfs(0)[0]
	d = dfs(da[1])
	db = d[da[1]]
	diam = []
	v = db[1]
	while v != da[1]:
		diam.append(v)
		v = p[v]
	diam.append(da[1])
	if len(diam) == n:
		print(n - 1)
		print(diam[0] + 1, diam[1] + 1, diam[-1] + 1)
	else:
		dset = set(diam)
		md = (0, 0)
		for i in diam[1:-1]:
			for j in g[i] - dset:
				md = max(md, d[j])
		print(len(diam) - 1 + md[0])
		print(diam[0] + 1, diam[-1] + 1, md[1] + 1)
main()


import sys
from collections import deque
reader = (line.rstrip() for line in sys.stdin)
input = reader.__next__
n = int(input())
g = [[] for _ in range(n)]
for _ in range(n - 1):
	(v, to) = map(int, input().split())
	v -= 1
	to -= 1
	g[v].append(to)
	g[to].append(v)
queue = deque([(0, 0)])
visited = [False] * n
while queue:
	(v, d) = queue.popleft()
	visited[v] = True
	for to in g[v]:
		if not visited[to]:
			queue.append((to, d + 1))
a = v
queue = deque([(a, 0)])
prev = [-1] * n
for i in range(n):
	visited[i] = False
while queue:
	(v, d) = queue.popleft()
	visited[v] = True
	for to in g[v]:
		if not visited[to]:
			queue.append((to, d + 1))
			prev[to] = v
(b, ctr) = (v, d)
for i in range(n):
	visited[i] = False
curr = prev[b]
nxt = b
prv = prev[curr]
add = 0
if a != 0 and b != 0:
	c = 0
elif a != 1 and b != 1:
	c = 1
else:
	c = 2
while curr != a:
	visited[curr] = True
	for to in g[curr]:
		if to == nxt or to == prv:
			continue
		queue = deque([(to, 1)])
		while queue:
			(v, d) = queue.popleft()
			visited[v] = True
			for to in g[v]:
				if not visited[to]:
					queue.append((to, d + 1))
		if add < d:
			(c, add) = (v, d)
	nxt = curr
	curr = prev[curr]
	prv = prev[curr]
print(ctr + add)
print(a + 1, b + 1, c + 1)


from collections import namedtuple, deque
from sys import stdin

def load_graph():
	n = int(stdin.readline())
	G = [set() for i in range(n)]
	for line in stdin.readlines():
		(a, b) = line.split()
		(a, b) = (int(a) - 1, int(b) - 1)
		G[a].add(b)
		G[b].add(a)
	return G

def find_all_distances(G, node):
	distances = [None] * len(G)
	distances[node] = 0
	queue = deque((node,))
	while len(queue) > 0:
		current_node = queue.popleft()
		for neighbor in G[current_node]:
			if distances[neighbor] is None:
				distances[neighbor] = distances[current_node] + 1
				queue.append(neighbor)
	return distances

def find_longest_pair(G):
	best_dist_0 = max(((d, i) for (i, d) in enumerate(find_all_distances(G, 0))))
	start_node = best_dist_0[1]
	best_dist_start = max(((d, i) for (i, d) in enumerate(find_all_distances(G, start_node))))
	(path_length, end_node) = best_dist_start
	return (path_length, start_node, end_node)

def find_maxdist_triplet(G):
	(path_length, path_a, path_b) = find_longest_pair(G)
	dists_a = find_all_distances(G, path_a)
	dists_b = find_all_distances(G, path_b)
	sum_dists = [(dists_a[i] + dists_b[i], i) for i in range(len(G)) if i != path_a and i != path_b]
	(best_c_dist_ab, best_c) = max(sum_dists)
	dist_sum = path_length + best_c_dist_ab
	return (dist_sum, path_a, path_b, best_c)
G = load_graph()
(dist_sum, path_a, path_b, path_c) = find_maxdist_triplet(G)
print(dist_sum // 2)
print(path_a + 1, path_b + 1, path_c + 1)


import sys, math
import io, os
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')
mod = int(1000000000.0) + 7
n = int(data())
g = [[] for i in range(n + 1)]
for i in range(n - 1):
	(u, v) = mdata()
	g[u].append(v)
	g[v].append(u)
ind = 1
for i in range(1, n + 1):
	if len(g[i]) == 1:
		ind = i
		break
q = [ind]
v = [0] * (n + 1)
vis = [0] * (n + 1)
m = 0
ans = 0
while q:
	a = q.pop()
	vis[a] = 1
	for i in g[a]:
		if vis[i] == 0:
			q.append(i)
			v[i] = v[a] + 1
			if v[i] > m:
				m = v[i]
				ind = i
x = ind
q = [ind]
v = [0] * (n + 1)
par = [0] * (n + 1)
m = 0
while q:
	a = q.pop()
	for i in g[a]:
		if par[a] != i:
			q.append(i)
			v[i] = v[a] + 1
			par[i] = a
			if v[i] > m:
				m = v[i]
				ind = i
y = ind
a = par[y]
ans = m
m = 0
ind = a
vis = [0] * (n + 1)
vis[y] = 1
while a != x:
	q = [a]
	while q:
		a1 = q.pop()
		vis[a1] = 1
		for i in g[a1]:
			if vis[i] == 0 and i != par[a1]:
				q.append(i)
				if v[i] - v[a] > m:
					m = v[i] - v[a]
					ind = i
	a = par[a]
z = ind
ans += m
out(ans)
print(x, y, z)


import sys
input = sys.stdin.readline
from collections import *

def bfs(sta):
	dist = [-1] * n
	dist[sta] = 0
	par = [-1] * n
	q = deque([sta])
	while q:
		v = q.popleft()
		for nv in G[v]:
			if dist[nv] == -1:
				dist[nv] = dist[v] + 1
				par[nv] = v
				q.append(nv)
	return (dist, par)

def mbfs():
	dist = [-1] * n
	l = [b]
	while par[l[-1]] != -1:
		l.append(par[l[-1]])
	q = deque([])
	for li in l:
		dist[li] = 0
		q.append(li)
	while q:
		v = q.popleft()
		for nv in G[v]:
			if dist[nv] == -1:
				dist[nv] = dist[v] + 1
				q.append(nv)
	return dist
n = int(input())
G = [[] for _ in range(n)]
for _ in range(n - 1):
	(u, v) = map(int, input().split())
	G[u - 1].append(v - 1)
	G[v - 1].append(u - 1)
(d1, _) = bfs(0)
M = 0
for i in range(n):
	if d1[i] > M:
		M = d1[i]
		a = i
(d2, par) = bfs(a)
M1 = 0
for i in range(n):
	if d2[i] > M1:
		M1 = d2[i]
		b = i
d3 = mbfs()
if d3 == [0] * n:
	for i in range(n):
		if i != a and i != b:
			print(M1)
			print(a + 1, b + 1, i + 1)
			exit()
M2 = 0
for i in range(n):
	if d3[i] > M2:
		M2 = d3[i]
		c = i
print(M1 + M2)
print(a + 1, b + 1, c + 1)


import os, sys
from io import IOBase, BytesIO
py2 = round(0.5)
if py2:
	from future_builtins import ascii, filter, hex, map, oct, zip
	range = xrange
BUFSIZE = 8192

class FastIO(BytesIO):
	newlines = 0

	def __init__(self, file):
		self._file = file
		self._fd = file.fileno()
		self.writable = 'x' in file.mode or 'w' in file.mode
		self.write = super(FastIO, self).write if self.writable else None

	def _fill(self):
		s = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
		self.seek((self.tell(), self.seek(0, 2), super(FastIO, self).write(s))[0])
		return s

	def read(self):
		while self._fill():
			pass
		return super(FastIO, self).read()

	def readline(self):
		while self.newlines == 0:
			s = self._fill()
			self.newlines = s.count(b'\n') + (not s)
		self.newlines -= 1
		return super(FastIO, self).readline()

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

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		if py2:
			self.write = self.buffer.write
			self.read = self.buffer.read
			self.readline = self.buffer.readline
		else:
			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')
import sys

class ostream:

	def __lshift__(self, a):
		sys.stdout.write(str(a))
		return self
cout = ostream()
endl = '\n'
n = int(input())
tre = [[] for i in range(n)]
for i in range(n - 1):
	(a, b) = map(int, input().split())
	tre[a - 1].append(b - 1)
	tre[b - 1].append(a - 1)
s = [0]
v = [False for i in range(n)]
h = {}
h[0] = 0
while s:
	x = s.pop()
	v[x] = True
	for j in tre[x]:
		if v[j]:
			continue
		s.append(j)
		h[j] = h[x] + 1
g = max(h.values())
for i in h:
	if g == h[i]:
		break
kk = i
v = [False for i in range(n)]
s = [i]
h = {}
h[i] = 0
par = {i: -1}
while s:
	x = s.pop()
	v[x] = True
	for j in tre[x]:
		if v[j]:
			continue
		s.append(j)
		h[j] = h[x] + 1
		par[j] = x
b = max(h.values())
for j in h:
	if b == h[j]:
		break
aze = set()
o = j
oo = j
while o != -1:
	aze.add(o)
	o = par[o]
az = list(aze)
h = {i: 0 for i in az}
v = [False for i in range(n)]
for u in az:
	v[u] = True
while az:
	x = az.pop()
	for j in tre[x]:
		if v[j]:
			continue
		v[x] = True
		az.append(j)
		h[j] = h[x] + 1
f = max(h.values())
for k in h:
	if h[k] == f and k not in [kk, oo]:
		break
print(b + f)
ans = [str(oo + 1), str(kk + 1), str(k + 1)]
print(' '.join(ans))


from collections import namedtuple, deque
from sys import stdin

def load_graph():
	n = int(stdin.readline())
	G = [set() for i in range(n)]
	for line in stdin.readlines():
		(a, b) = line.split()
		(a, b) = (int(a) - 1, int(b) - 1)
		G[a].add(b)
		G[b].add(a)
	return G

def find_longest_pair(G):
	Result = namedtuple('Result', ['depth', 'deep_node', 'path_length', 'path_a', 'path_b'])

	def compute_at_node(G, results, node):
		neighbor_results = []
		for neighbor in G[node]:
			if results[neighbor] is not None:
				neighbor_results.append(results[neighbor])
		if len(neighbor_results) == 0:
			return Result(depth=0, deep_node=current_node, path_length=0, path_a=current_node, path_b=current_node)
		else:
			best_path = max(neighbor_results, key=lambda r: r.path_length)
			best_depth_1 = max(neighbor_results, key=lambda r: r.depth)
			if len(neighbor_results) > 1:
				not_best = [r for r in neighbor_results if r is not best_depth_1]
				best_depth_2 = max(not_best, key=lambda r: r.depth)
				merge_path_length = best_depth_1.depth + best_depth_2.depth + 2
				merge_path_a = best_depth_1.deep_node
				merge_path_b = best_depth_2.deep_node
			else:
				merge_path_length = best_depth_1.depth + 1
				merge_path_a = best_depth_1.deep_node
				merge_path_b = current_node
			if best_path.path_length < merge_path_length:
				return Result(depth=best_depth_1.depth + 1, deep_node=best_depth_1.deep_node, path_length=merge_path_length, path_a=merge_path_a, path_b=merge_path_b)
			else:
				return Result(depth=best_depth_1.depth + 1, deep_node=best_depth_1.deep_node, path_length=best_path.path_length, path_a=best_path.path_a, path_b=best_path.path_b)
	visited = [False] * len(G)
	visited[0] = True
	results = [None] * len(G)
	queue = deque((0,))
	stack = [0]
	while len(queue) > 0:
		current_node = queue.popleft()
		for neighbor in G[current_node]:
			if not visited[neighbor]:
				visited[neighbor] = True
				queue.append(neighbor)
				stack.append(neighbor)
	for current_node in reversed(stack):
		results[current_node] = compute_at_node(G, results, current_node)
	return (results[0].path_length, results[0].path_a, results[0].path_b)

def find_all_distances(G, node):
	distances = [None] * len(G)
	distances[node] = 0
	queue = deque((node,))
	while len(queue) > 0:
		current_node = queue.popleft()
		for neighbor in G[current_node]:
			if distances[neighbor] is None:
				distances[neighbor] = distances[current_node] + 1
				queue.append(neighbor)
	return distances

def find_maxdist_triplet(G):
	(path_length, path_a, path_b) = find_longest_pair(G)
	dists_a = find_all_distances(G, path_a)
	dists_b = find_all_distances(G, path_b)
	sum_dists = [(dists_a[i] + dists_b[i], i) for i in range(len(G)) if i != path_a and i != path_b]
	(best_c_dist_ab, best_c) = max(sum_dists)
	dist_sum = path_length + best_c_dist_ab
	return (dist_sum, path_a, path_b, best_c)
G = load_graph()
(dist_sum, path_a, path_b, path_c) = find_maxdist_triplet(G)
print(dist_sum // 2)
print(path_a + 1, path_b + 1, path_c + 1)