package main
import (
"bufio"
"fmt"
"os"
)
var (
scanner = bufio.NewScanner(os.Stdin)
)
func init() {
scanner.Split(bufio.ScanWords)
scanner.Buffer(make([]byte, 1024*1024), 1024*1024*10)
}
func nextInt() int {
scanner.Scan()
res := 0
for _, b := range scanner.Bytes() {
res = res*10 + int(b-'0')
}
return res
}
func nextInt64() int64 {
scanner.Scan()
var res int64
for _, b := range scanner.Bytes() {
res = res*10 + int64(b-'0')
}
return res
}
func max(a, b int64) int64 {
if a > b {
return a
}
return b
}
type Top3 struct {
v [3]int64
id [3]int
}
func (t *Top3) add(val int64, id int) {
if val > t.v[0] {
t.v[2], t.id[2] = t.v[1], t.id[1]
t.v[1], t.id[1] = t.v[0], t.id[0]
t.v[0], t.id[0] = val, id
} else if val > t.v[1] {
t.v[2], t.id[2] = t.v[1], t.id[1]
t.v[1], t.id[1] = val, id
} else if val > t.v[2] {
t.v[2], t.id[2] = val, id
}
}
func main() {
if !scanner.Scan() {
return
}
n := 0
for _, b := range scanner.Bytes() {
n = n*10 + int(b-'0')
}
a := make([]int64, n+1)
for i := 1; i <= n; i++ {
a[i] = nextInt64()
}
adj := make([][]int, n+1)
for i := 0; i < n-1; i++ {
u := nextInt()
v := nextInt()
adj[u] = append(adj[u], v)
adj[v] = append(adj[v], u)
}
m1 := make([]int64, n+1)
m2 := make([]int64, n+1)
m3 := make([]int64, n+1)
var dfs1 func(u, p int)
dfs1 = func(u, p int) {
var max_m2, second_max_m2 int64
for _, v := range adj[u] {
if v == p {
continue
}
dfs1(v, u)
m1[u] = max(m1[u], m1[v])
val := max(0, m2[v])
if val > max_m2 {
second_max_m2 = max_m2
max_m2 = val
} else if val > second_max_m2 {
second_max_m2 = val
}
}
m2[u] = a[u] + max_m2
m3[u] = a[u] + max_m2 + second_max_m2
m1[u] = max(m1[u], m3[u])
}
dfs1(1, 0)
var ans int64
var dfs2 func(u, p int, out1, out2 int64)
dfs2 = func(u, p int, out1, out2 int64) {
top2_val1 := Top3{v: [3]int64{0, 0, 0}, id: [3]int{-1, -1, -1}}
top3_val2 := Top3{v: [3]int64{0, 0, 0}, id: [3]int{-1, -1, -1}}
if p != 0 {
top2_val1.add(out1, p)
top3_val2.add(max(0, out2), p)
}
for _, v := range adj[u] {
if v != p {
top2_val1.add(m1[v], v)
top3_val2.add(max(0, m2[v]), v)
}
}
for _, v := range adj[u] {
if v == p {
continue
}
max_val1_ex := top2_val1.v[0]
if top2_val1.id[0] == v {
max_val1_ex = top2_val1.v[1]
}
var m2_ex_1, m2_ex_2 int64
if top3_val2.id[0] == v {
m2_ex_1 = top3_val2.v[1]
m2_ex_2 = top3_val2.v[2]
} else if top3_val2.id[1] == v {
m2_ex_1 = top3_val2.v[0]
m2_ex_2 = top3_val2.v[2]
} else {
m2_ex_1 = top3_val2.v[0]
m2_ex_2 = top3_val2.v[1]
}
new_out2 := a[u] + m2_ex_1
new_out3 := a[u] + m2_ex_1 + m2_ex_2
new_out1 := max(max_val1_ex, new_out3)
ans = max(ans, m1[v]+new_out1)
dfs2(v, u, new_out1, new_out2)
}
}
dfs2(1, 0, 0, 0)
fmt.Println(ans)
}