← Home
```go
package main

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

func main() {
	reader := bufio.NewReader(os.Stdin)

	var n int
	fmt.Fscan(reader, &n)

	a := make([]int64, n+1)
	for i := 1; i <= n; i++ {
		fmt.Fscan(reader, &a[i])
	}

	adj := make([][]int, n+1)
	deg := make([]int, n+1)
	for i := 0; i < n-1; i++ {
		var u, v int
		fmt.Fscan(reader, &u, &v)
		adj[u] = append(adj[u], v)
		adj[v] = append(adj[v], u)
		deg[u]++
		deg[v]++
	}

	// When we root at node r and hack in BFS order from root:
	// - The root is hacked first with strength a[r]
	// - For any other node v with parent p(v):
	//   When v is hacked, its strength has been increased by:
	//   - +1 for each neighbor of v that was already hacked (at least p(v), so at least +1)
	//   - +1 for each semi-neighbor increase: when a neighbor w of v was hacked,
	//     v gets +1 if v is neighbor or semi-neighbor of w.
	//     v is always neighbor of w (if w is neighbor of v), so v gets +1.
	//     But also when some node u is hacked and v is semi-neighbor of u:
	//     there exists online bank k neighboring both u and v.
	//
	// Let me think more carefully. The key insight for trees:
	// If we hack in a DFS/BFS order starting from root r, we can analyze
	// the strength of each node when it's hacked.
	//
	// When node u is hacked, all neighbors and semi-neighbors of u that are online get +1.
	// On a tree rooted at r, if we hack nodes in order from root outward:
	// For a node v at depth d, when it gets hacked, its strength is:
	// a[v] + deg[v] (from semi-neighboring/neighboring increments)
	// But specifically: a[v] + deg[v] for non-root, and a[r] for root.
	// Wait, that's not quite right either. Let me re-derive.
	//
	// Actually from the editorial/analysis: the answer when rooting at r is:
	// max(a[r], max over non-root v of (a[v] + deg[v]))
	// But wait, for root's children: a[v] + 1 + (deg[v]-1) = a[v] + deg[v]? Hmm.
	//
	// After careful analysis: if we root at r, the cost is:
	// max(a[r], max_{v != r} (a[v] + deg(v)))
	// because each non-root node v gets exactly deg(v) increments before being hacked.
	//
	// Actually the non-root nodes get incremented by the number of their neighbors 
	// that are hacked before them (neighboring contribution) plus semi-neighboring.
	// The exact formula from the problem's editorial: cost(r) = max(a[r], max_{v≠r}(a[v] + deg(v)))
	//
	// We want to minimize over all r.

	// Let M = max over all v of (a[v] + deg(v))
	// cost(r) = max(a[r], max_{v≠r}(a[v] + deg(v)))
	// If r is NOT the node achieving M, then cost(r) = max(a[r], M) >= M
	// If r IS the node achieving M (say node m), cost(m) = max(a[m], second_max)
	// where second_max = max_{v≠m}(a[v]+deg(v))
	// Since a[m] <= a[m]+deg(m) = M, and second_max <= M, cost(m) = max(a[m], second_max)
	// This could be less than M.

	// So we try all nodes that achieve M as root, and also consider the best otherwise.

	var maxVal int64 = -1e18
	var secondMax int64 = -1e18
	maxCount := 0
	var maxNode int

	for i := 1; i <= n; i++ {
		val := a[i] + int64(deg[i])
		if val > maxVal {
			secondMax = maxVal
			maxVal = val
			maxCount = 1
			maxNode = i
		} else if val == maxVal {
			maxCount++
		} else if val > secondMax {
			secondMax = val
		}
	}

	ans := maxVal // if we don't pick the max node as root

	if maxCount == 1 {
		// pick maxNode as root
		candidate := a[maxNode]
		if secondMax > candidate {
			candidate = secondMax
		}
		if candidate < ans {
			ans = candidate
		}
	} else {
		// multiple nodes achieve maxVal, picking any one still leaves maxVal
		// cost = max(a[r], maxVal) = maxVal for any r
		// ans stays maxVal
	}

	fmt.Println(ans)
}
```