← Home
```go
package main

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

type FastScanner struct {
	r *bufio.Reader
}

func NewFastScanner() *FastScanner {
	return &FastScanner{r: bufio.NewReaderSize(os.Stdin, 1<<20)}
}

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

func bfsFarthest(adj [][]int, start int) (far int, dist []int, parent []int) {
	n := len(adj) - 1
	dist = make([]int, n+1)
	parent = make([]int, n+1)
	for i := 1; i <= n; i++ {
		dist[i] = -1
		parent[i] = 0
	}
	q := make([]int, 0, n)
	dist[start] = 0
	q = append(q, start)
	head := 0
	for head < len(q) {
		v := q[head]
		head++
		for _, to := range adj[v] {
			if dist[to] == -1 {
				dist[to] = dist[v] + 1
				parent[to] = v
				q = append(q, to)
			}
		}
	}
	far = start
	for i := 1; i <= n; i++ {
		if dist[i] > dist[far] {
			far = i
		}
	}
	return
}

func bfsWithBlocked(adj [][]int, start int, blocked []bool) (far int, dist []int) {
	n := len(adj) - 1
	dist = make([]int, n+1)
	for i := 1; i <= n; i++ {
		dist[i] = -1
	}
	if blocked[start] {
		return start, dist
	}
	q := make([]int, 0, n)
	dist[start] = 0
	q = append(q, start)
	head := 0
	for head < len(q) {
		v := q[head]
		head++
		for _, to := range adj[v] {
			if blocked[to] || dist[to] != -1 {
				continue
			}
			dist[to] = dist[v] + 1
			q = append(q, to)
		}
	}
	far = start
	for i := 1; i <= n; i++ {
		if dist[i] > dist[far] {
			far = i
		}
	}
	return
}

func main() {
	fs := NewFastScanner()
	n := fs.NextInt()
	adj := make([][]int, n+1)
	for i := 0; i < n-1; i++ {
		a := fs.NextInt()
		b := fs.NextInt()
		adj[a] = append(adj[a], b)
		adj[b] = append(adj[b], a)
	}

	u, _, _ := bfsFarthest(adj, 1)
	v, distU, parentU := bfsFarthest(adj, u)
	diamLen := distU[v]

	onPath := make([]bool, n+1)
	cur := v
	for cur != 0 {
		onPath[cur] = true
		if cur == u {
			break
		}
		cur = parentU[cur]
	}

	a := u
	b := v
	c := 1

	_, distFromPath := bfsWithBlocked(adj, u, onPath)
	bestDist := -1
	bestNode := -1
	for i := 1; i <= n; i++ {
		if distFromPath[i] > bestDist {
			bestDist = distFromPath[i]
			bestNode = i
		}
	}
	if bestNode == -1 {
		for i := 1; i <= n; i++ {
			if i != a && i != b {
				bestNode = i
				break
			}
		}
		bestDist = 0
	}
	c = bestNode

	res := diamLen + bestDist
	if bestDist == -1 {
		res = diamLen
	}

	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	fmt.Fprintln(out, res)
	fmt.Fprintln(out, a, b, c)
	out.Flush()
}
```