← Home
package main

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

func readInt(reader *bufio.Reader) int {
	var res int
	var c byte
	var err error
	for {
		c, err = reader.ReadByte()
		if err != nil {
			return res
		}
		if c >= '0' && c <= '9' {
			break
		}
	}
	res = int(c - '0')
	for {
		c, err = reader.ReadByte()
		if err != nil || c < '0' || c > '9' {
			break
		}
		res = res*10 + int(c - '0')
	}
	return res
}

type Edge struct {
	to     int
	weight int
}

var n, l, r int
var adj [][]Edge

var sz []int
var removed []bool

func getSizes(u, p int) {
	sz[u] = 1
	for _, edge := range adj[u] {
		if edge.to != p && !removed[edge.to] {
			getSizes(edge.to, u)
			sz[u] += sz[edge.to]
		}
	}
}

func getCentroid(u, p, total int) int {
	for _, edge := range adj[u] {
		if edge.to != p && !removed[edge.to] {
			if sz[edge.to] > total/2 {
				return getCentroid(edge.to, u, total)
			}
		}
	}
	return u
}

type NodeData struct {
	id        int
	depth     int
	weight    int
	parentIdx int
}

type SubtreeData struct {
	maxDepth int
	nodes    []NodeData
}

type CentroidData struct {
	id       int
	subtrees []SubtreeData
}

var centroids []CentroidData

func buildCentroid(u int) {
	getSizes(u, -1)
	total := sz[u]
	c := getCentroid(u, -1, total)

	cData := CentroidData{id: c, subtrees: make([]SubtreeData, 0)}

	for _, edge := range adj[c] {
		if !removed[edge.to] {
			st := SubtreeData{maxDepth: 0, nodes: make([]NodeData, 0)}

			type BFSNode struct {
				id, p, depth, weight, pIdx int
			}
			q := []BFSNode{{edge.to, c, 1, edge.weight, -1}}

			for head := 0; head < len(q); head++ {
				curr := q[head]
				st.nodes = append(st.nodes, NodeData{
					id:        curr.id,
					depth:     curr.depth,
					weight:    curr.weight,
					parentIdx: curr.pIdx,
				})
				if curr.depth > st.maxDepth {
					st.maxDepth = curr.depth
				}

				myIdx := len(st.nodes) - 1
				for _, nxt := range adj[curr.id] {
					if nxt.to != curr.p && !removed[nxt.to] {
						q = append(q, BFSNode{nxt.to, curr.id, curr.depth+1, nxt.weight, myIdx})
					}
				}
			}
			cData.subtrees = append(cData.subtrees, st)
		}
	}

	sort.Slice(cData.subtrees, func(i, j int) bool {
		return cData.subtrees[i].maxDepth < cData.subtrees[j].maxDepth
	})

	centroids = append(centroids, cData)

	removed[c] = true
	for _, edge := range adj[c] {
		if !removed[edge.to] {
			buildCentroid(edge.to)
		}
	}
}

type BestData struct {
	sum  int
	node int
}

var best []BestData
var cur_best []BestData
var deque []int
var sums []int

func check(M int) (bool, int, int) {
	for _, cData := range centroids {
		if len(cData.subtrees) == 0 {
			continue
		}
		M_depth := 0
		best[0] = BestData{sum: 0, node: cData.id}

		for _, st := range cData.subtrees {
			for d := 1; d <= st.maxDepth; d++ {
				cur_best[d] = BestData{sum: -1e9, node: -1}
			}

			for i, nd := range st.nodes {
				val := 1
				if nd.weight < M {
					val = -1
				}
				if nd.parentIdx == -1 {
					sums[i] = val
				} else {
					sums[i] = sums[nd.parentIdx] + val
				}

				if sums[i] > cur_best[nd.depth].sum {
					cur_best[nd.depth] = BestData{sum: sums[i], node: nd.id}
				}
			}

			current_R := -1
			qHead, qTail := 0, 0

			for d := st.maxDepth; d >= 1; d-- {
				if cur_best[d].sum <= -1e8 {
					continue
				}
				L := l - d
				if L < 0 {
					L = 0
				}
				R := r - d
				if R > M_depth {
					R = M_depth
				}

				if L > R {
					continue
				}

				for current_R < R {
					current_R++
					if best[current_R].sum > -1e8 {
						for qTail > qHead && best[deque[qTail-1]].sum <= best[current_R].sum {
							qTail--
						}
						deque[qTail] = current_R
						qTail++
					}
				}

				for qHead < qTail && deque[qHead] < L {
					qHead++
				}

				if qHead < qTail {
					if cur_best[d].sum+best[deque[qHead]].sum >= 0 {
						for i := 0; i <= M_depth; i++ {
							best[i] = BestData{sum: -1e9, node: -1}
						}
						return true, cur_best[d].node, best[deque[qHead]].node
					}
				}
			}

			for d := 1; d <= st.maxDepth; d++ {
				if cur_best[d].sum > best[d].sum {
					best[d] = cur_best[d]
				}
			}
			if st.maxDepth > M_depth {
				M_depth = st.maxDepth
			}
		}

		for d := 0; d <= M_depth; d++ {
			best[d] = BestData{sum: -1e9, node: -1}
		}
	}
	return false, -1, -1
}

func main() {
	reader := bufio.NewReaderSize(os.Stdin, 65536)
	n = readInt(reader)
	l = readInt(reader)
	r = readInt(reader)

	adj = make([][]Edge, n+1)
	uniqueWeights := make([]int, 0, n-1)

	for i := 0; i < n-1; i++ {
		u := readInt(reader)
		v := readInt(reader)
		w := readInt(reader)
		adj[u] = append(adj[u], Edge{v, w})
		adj[v] = append(adj[v], Edge{u, w})
		uniqueWeights = append(uniqueWeights, w)
	}

	sz = make([]int, n+1)
	removed = make([]bool, n+1)

	buildCentroid(1)

	best = make([]BestData, n+1)
	cur_best = make([]BestData, n+1)
	deque = make([]int, n+1)
	sums = make([]int, n+1)

	for i := 0; i <= n; i++ {
		best[i] = BestData{sum: -1e9, node: -1}
		cur_best[i] = BestData{sum: -1e9, node: -1}
	}

	sort.Ints(uniqueWeights)
	var wList []int
	for i, w := range uniqueWeights {
		if i == 0 || w != uniqueWeights[i-1] {
			wList = append(wList, w)
		}
	}

	left := 0
	right := len(wList) - 1
	bestU, bestV := -1, -1

	for left <= right {
		mid := left + (right-left)/2
		ok, u, v := check(wList[mid])
		if ok {
			bestU = u
			bestV = v
			left = mid + 1
		} else {
			right = mid - 1
		}
	}

	if bestU != -1 && bestV != -1 {
		fmt.Printf("%d %d\n", bestU, bestV)
	}
}