← Home
```go
package main

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

const INF = 1 << 60

var n int
var c []int64
var adj [][]int
var children [][]int
var m []int
var full []int64
var spec []int64
var used []bool
var called [][]bool

func min(a, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

func dfs(u, par int) {
	children[u] = []int{}
	isLeaf := true
	m[u] = 0
	for _, v := range adj[u] {
		if v != par {
			isLeaf = false
			children[u] = append(children[u], v)
			dfs(v, u)
			m[u] += m[v]
		}
	}
	if isLeaf && u != 1 {
		m[u] = 1
	}

	k := len(children[u])
	if k == 0 {
		// leaf
		full[u] = c[u]
		spec[u] = 0
		return
	}

	// compute full
	var sumFull int64 = 0
	for _, v := range children[u] {
		if full[v] >= INF {
			sumFull = INF
			break
		}
		sumFull += full[v]
	}
	fullOptA := sumFull

	var minB int64 = INF
	for j := 0; j < k; j++ {
		v := children[u][j]
		if spec[v] >= INF {
			continue
		}
		cost := c[u] + (sumFull - full[v]) + spec[v]
		if cost < minB {
			minB = cost
		}
	}
	if minB >= INF && fullOptA >= INF {
		full[u] = INF
	} else {
		full[u] = min(fullOptA, minB)
	}

	// compute special
	var minS int64 = INF
	for j := 0; j < k; j++ {
		v := children[u][j]
		if spec[v] >= INF {
			continue
		}
		cost := (sumFull - full[v]) + spec[v]
		if cost < minS {
			minS = cost
		}
	}
	spec[u] = minS
}

func collectUsed(u int, isSpec bool) {
	idx := 0
	if isSpec {
		idx = 1
	}
	if called[u][idx] {
		return
	}
	called[u][idx] = true

	k := len(children[u])
	if k == 0 {
		// leaf
		if !isSpec {
			used[u] = true
		}
		return
	}

	var target int64
	var sumFull int64 = 0
	for _, v := range children[u] {
		sumFull += full[v]
	}
	if isSpec {
		target = spec[u]
		if target >= INF {
			return
		}
		// for special: don't buy u
		// compute minS and the min js
		var mb int64 = INF
		costs := make([]int64, k)
		for j := 0; j < k; j++ {
			v := children[u][j]
			if spec[v] >= INF {
				costs[j] = INF
				continue
			}
			costs[j] = sumFull - full[v] + spec[v]
			if costs[j] < mb {
				mb = costs[j]
			}
		}
		var count int = 0
		var j0 int = -1
		for j := 0; j < k; j++ {
			if costs[j] == mb {
				count++
				if count == 1 {
					j0 = j
				} else {
					j0 = -2
				}
			}
		}
		isMinS := make([]bool, k)
		for j := 0; j < k; j++ {
			isMinS[j] = (costs[j] == mb)
		}
		// no buy u
		for p := 0; p < k; p++ {
			// assign full to p if exists j != p with isMinS[j]
			hasFull := false
			isUnique := (count == 1 && j0 >= 0)
			onlyMinIsP := isUnique && j0 == p
			if !onlyMinIsP {
				hasFull = true
			}
			// assign special to p if isMinS[p]
			hasSpec := isMinS[p]

			vv := children[u][p]
			if hasFull {
				collectUsed(vv, false)
			}
			if hasSpec {
				collectUsed(vv, true)
			}
		}
		return
	}

	// full
	target = full[u]
	if target >= INF {
		return
	}
	// buy u if some B achieves target
	buyU := false
	var mb int64 = INF
	costs := make([]int64, k)
	for j := 0; j < k; j++ {
		v := children[u][j]
		if spec[v] >= INF {
			costs[j] = INF
			continue
		}
		costs[j] = c[u] + sumFull - full[v] + spec[v]
		if costs[j] < mb {
			mb = costs[j]
		}
	}
	if mb == target {
		buyU = true
	}
	if buyU {
		used[u] = true
	}

	var count int = 0
	var j0 int = -1
	for j := 0; j < k; j++ {
		if costs[j] == mb {
			count++
			if count == 1 {
				j0 = j
			} else {
				j0 = -2
			}
		}
	}
	isMinB := make([]bool, k)
	for j := 0; j < k; j++ {
		isMinB[j] = (costs[j] == mb)
	}

	for p := 0; p < k; p++ {
		// assign full
		hasFull := (sumFull == target)
		if mb == target {
			isUnique := (count == 1 && j0 >= 0)
			onlyMinIsP := isUnique && j0 == p
			if !onlyMinIsP {
				hasFull = true
			}
		}
		// assign special
		hasSpec := false
		if mb == target && isMinB[p] {
			hasSpec = true
		}

		vv := children[u][p]
		if hasFull {
			collectUsed(vv, false)
		}
		if hasSpec {
			collectUsed(vv, true)
		}
	}
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)

	line, _ := in.ReadString('\n')
	n, _ = strconv.Atoi(strings.TrimSpace(line))

	line, _ = in.ReadString('\n')
	parts := strings.Fields(line)
	c = make([]int64, n+1)
	for i := 1; i <= n; i++ {
		c[i], _ = strconv.ParseInt(parts[i-1], 10, 64)
	}

	adj = make([][]int, n+1)
	for i := 0; i < n-1; i++ {
		line, _ = in.ReadString('\n')
		parts = strings.Fields(line)
		a, _ := strconv.Atoi(parts[0])
		b, _ := strconv.Atoi(parts[1])
		adj[a] = append(adj[a], b)
		adj[b] = append(adj[b], a)
	}

	children = make([][]int, n+1)
	m = make([]int, n+1)
	full = make([]int64, n+1)
	spec = make([]int64, n+1)
	for i := 0; i <= n; i++ {
		full[i] = INF
		spec[i] = INF
	}

	dfs(1, 0)

	used = make([]bool, n+1)
	called = make([][]bool, n+1)
	for i := 0; i <= n; i++ {
		called[i] = make([]bool, 2)
	}

	collectUsed(1, false)

	var res []int
	for i := 1; i <= n; i++ {
		if used[i] {
			res = append(res, i)
		}
	}
	sort.Ints(res)

	fmt.Fprint(out, full[1], " ", len(res), "\n")
	for i, v := range res {
		if i > 0 {
			fmt.Fprint(out, " ")
		}
		fmt.Fprint(out, v)
	}
	fmt.Fprint(out, "\n")
	out.Flush()
}
```